经过本教程您能够学习到:node
NN以及2NN的工做机制以下图所示web
其中chkpoint检查时间参数设置shell
[hdfs-default.xml] <property> <name>dfs.namenode.checkpoint.period</name> <value>3600</value> </property>
一、namenode工做json
二、Secondary NameNode工做安全
前面咱们提到NN处理过程当中的两类关键文件,一个是编辑日志,另外一个则是镜像文件,咱们来看看他们究竟是什么。bash
位于/opt/module/hadoop-2.7.2/data/tmp/dfs/name/current目录中产生的文件。他们产生于namenode被格式化以后,将产生以下文件数据结构
edits_0000000000000000000 fsimage_0000000000000000000.md5 seen_txid VERSION
其中:oop
[root@h133 current]# pwd /opt/module/hadoop-2.7.2/data/tmp/dfs/name/current [root@h133 current]# ll 总用量 3204 ... -rw-r--r--. 1 root root 42 1月 4 10:47 edits_0000000000000000086-0000000000000000087 -rw-r--r--. 1 root root 42 1月 4 11:42 edits_0000000000000000088-0000000000000000089 -rw-r--r--. 1 root root 42 1月 4 12:37 edits_0000000000000000090-0000000000000000091 -rw-r--r--. 1 root root 3406 1月 4 13:32 edits_0000000000000000092-0000000000000000134 -rw-r--r--. 1 root root 42 1月 4 14:28 edits_0000000000000000135-0000000000000000136 -rw-r--r--. 1 root root 1048576 1月 4 14:28 edits_inprogress_0000000000000000137 -rw-r--r--. 1 root root 1027 1月 4 13:33 fsimage_0000000000000000134 -rw-r--r--. 1 root root 62 1月 4 13:33 fsimage_0000000000000000134.md5 -rw-r--r--. 1 root root 1027 1月 4 14:28 fsimage_0000000000000000136 -rw-r--r--. 1 root root 62 1月 4 14:28 fsimage_0000000000000000136.md5 -rw-r--r--. 1 root root 4 1月 4 14:28 seen_txid -rw-r--r--. 1 root root 208 1月 3 15:10 VERSION
seen_txid的内容比较简单,单纯的一个数字,表明最后一个edits_的序号,咱们能够直接经过cat命令进行查看:布局
[root@h133 current]# cat seen_txid 137
137,恰好对应的edits_inprogress当前的下标。学习
镜像文件,即fsimage文件,前面提到,他的内容已是序列化字节码,所以咱们直接查看的话,会出现乱码。官方提供了命令方便咱们查看内容:
hdfs oiv -p 解码进程 -i 输入——镜像文件 -o 输出——转换后文件输出路径
解码进程通常使用XML,或者使用默认的Ls。
接下来咱们使用XML解码进程将文件转化为一个xml文件,而后在本身的机器上使用比较好的编译器查看XML内容
hdfs oiv -p XML -i fsimage_0000000000000000136 -o myfsimage.xml
我甚至觉得支持json格式,尝试了一下不行,但愿之后的版本支持输出json格式。json & yml,这两个一个是数据传输、一个是文件配置的最佳选择。
查看文件内容以下:
<?xml version="1.0"?> <fsimage> <NameSection> <genstampV1>1000</genstampV1> <genstampV2>1014</genstampV2> <genstampV1Limit>0</genstampV1Limit> <lastAllocatedBlockId>1073741838</lastAllocatedBlockId> <txid>136</txid> </NameSection> <INodeSection> <lastInodeId>16403</lastInodeId> <inode> <id>16385</id> <type>DIRECTORY</type> <name></name> <mtime>1546499650677</mtime> <permission>root:supergroup:rwxr-xr-x</permission> <nsquota>9223372036854775807</nsquota> <dsquota>-1</dsquota> </inode> <inode> <id>16386</id> <type>DIRECTORY</type> <name>user</name> <mtime>1546579469553</mtime> <permission>root:supergroup:rwxr-xr-x</permission> <nsquota>-1</nsquota> <dsquota>-1</dsquota> </inode> <inode> <id>16387</id> <type>DIRECTORY</type> <name>zhaoyi</name> <mtime>1546502296962</mtime> <permission>root:supergroup:rwxr-xr-x</permission> <nsquota>-1</nsquota> <dsquota>-1</dsquota> </inode> ....
不难看出,该文件记录了咱们HDFS文件目录结构以及一些inode信息。
接下来咱们转化编辑日志文件(edits_xxxx)为XML格式。他使用另外一个命令操做:
hdfs oev -p 文件类型 -i 编辑日志 -o 转换后文件输出路径
在执行此操做以前,咱们就直接转换,发现最新的edits文件中并无任何数据,说明已经进行过一次合并(参见图示)。接下来咱们上传一个文件,而后在进行转换
dfs oev -p XML -i edits_inprogress_0000000000000000139 -o edits.xml
获得以下的XML文件内容:
<?xml version="1.0" encoding="UTF-8"?> <EDITS> <EDITS_VERSION>-63</EDITS_VERSION> <RECORD> <OPCODE>OP_START_LOG_SEGMENT</OPCODE> <DATA> <TXID>139</TXID> </DATA> </RECORD> <RECORD> <OPCODE>OP_ADD</OPCODE> <DATA> <TXID>140</TXID> <LENGTH>0</LENGTH> <INODEID>16404</INODEID> <PATH>/seen_txid._COPYING_</PATH> <REPLICATION>3</REPLICATION> <MTIME>1546588237534</MTIME> <ATIME>1546588237534</ATIME> <BLOCKSIZE>134217728</BLOCKSIZE> <CLIENT_NAME>DFSClient_NONMAPREDUCE_302138823_1</CLIENT_NAME> <CLIENT_MACHINE>192.168.102.133</CLIENT_MACHINE> <OVERWRITE>true</OVERWRITE> <PERMISSION_STATUS> <USERNAME>root</USERNAME> <GROUPNAME>supergroup</GROUPNAME> <MODE>420</MODE> </PERMISSION_STATUS> <RPC_CLIENTID>d56baf74-71a1-4e2e-a64c-9b6ba88d5552</RPC_CLIENTID> <RPC_CALLID>3</RPC_CALLID> </DATA> </RECORD> <RECORD> <OPCODE>OP_ALLOCATE_BLOCK_ID</OPCODE> <DATA> <TXID>141</TXID> <BLOCK_ID>1073741839</BLOCK_ID> </DATA> </RECORD> <RECORD> <OPCODE>OP_SET_GENSTAMP_V2</OPCODE> <DATA> <TXID>142</TXID> <GENSTAMPV2>1015</GENSTAMPV2> </DATA> </RECORD> <RECORD> <OPCODE>OP_ADD_BLOCK</OPCODE> <DATA> <TXID>143</TXID> <PATH>/seen_txid._COPYING_</PATH> <BLOCK> <BLOCK_ID>1073741839</BLOCK_ID> <NUM_BYTES>0</NUM_BYTES> <GENSTAMP>1015</GENSTAMP> </BLOCK> <RPC_CLIENTID></RPC_CLIENTID> <RPC_CALLID>-2</RPC_CALLID> </DATA> </RECORD> <RECORD> <OPCODE>OP_CLOSE</OPCODE> <DATA> <TXID>144</TXID> <LENGTH>0</LENGTH> <INODEID>0</INODEID> <PATH>/seen_txid._COPYING_</PATH> <REPLICATION>3</REPLICATION> <MTIME>1546588238055</MTIME> <ATIME>1546588237534</ATIME> <BLOCKSIZE>134217728</BLOCKSIZE> <CLIENT_NAME></CLIENT_NAME> <CLIENT_MACHINE></CLIENT_MACHINE> <OVERWRITE>false</OVERWRITE> <BLOCK> <BLOCK_ID>1073741839</BLOCK_ID> <NUM_BYTES>4</NUM_BYTES> <GENSTAMP>1015</GENSTAMP> </BLOCK> <PERMISSION_STATUS> <USERNAME>root</USERNAME> <GROUPNAME>supergroup</GROUPNAME> <MODE>420</MODE> </PERMISSION_STATUS> </DATA> </RECORD> <RECORD> <OPCODE>OP_RENAME_OLD</OPCODE> <DATA> <TXID>145</TXID> <LENGTH>0</LENGTH> <SRC>/seen_txid._COPYING_</SRC> <DST>/seen_txid</DST> <TIMESTAMP>1546588238066</TIMESTAMP> <RPC_CLIENTID>d56baf74-71a1-4e2e-a64c-9b6ba88d5552</RPC_CLIENTID> <RPC_CALLID>8</RPC_CALLID> </DATA> </RECORD> </EDITS>
从中能够了解到咱们往根路径下上传了一个seen.txid文件以后的编辑日志的记录信息。不少状况下,该文件可能会具备不少的历史数据。这对于咱们想单独调试某个操做的时候,没法定位准备的日志,这就须要咱们“清空”最新的edits文件的历史数据。
这就须要咱们滚动当前的日志了。
如何滚动?调用命令
hdfs dfsadmin -rollEdtis
例如:
[root@h133 current]# hdfs dfsadmin -rollEdits Successfully rolled edit logs. New segment starts at txid 147
能够看到,新的分片id变成了147,咱们也能够查看当前最新的分片日志文件为edits_inprogress_0000000000000000147:
[root@h133 current]# ll edits* -rw-r--r--. 1 root root 42 1月 3 15:12 edits_0000000000000000001-0000000000000000002 .... -rw-r--r--. 1 root root 42 1月 4 15:23 edits_0000000000000000137-0000000000000000138 -rw-r--r--. 1 root root 527 1月 4 15:59 edits_0000000000000000139-0000000000000000146 -rw-r--r--. 1 root root 1048576 1月 4 15:59 edits_inprogress_0000000000000000147
转化XML的日志进行查看,文件内容就比较干净了,方便咱们进行一些调试:
[root@h133 current]# hdfs oev -p XML -i edits_inprogress_0000000000000000147 -o edits.xml [root@h133 current]# cat edits.xml <?xml version="1.0" encoding="UTF-8"?> <EDITS> <EDITS_VERSION>-63</EDITS_VERSION> <RECORD> <OPCODE>OP_START_LOG_SEGMENT</OPCODE> <DATA> <TXID>147</TXID> </DATA> </RECORD> </EDITS>
该文件namenode中一些版本号的信息。
root@h133 current]# cat VERSION #Thu Jan 03 15:10:44 CST 2019 namespaceID=1140718114 clusterID=CID-5b84c9ed-504a-4885-9e26-b9e99eefaf21 cTime=0 storageType=NAME_NODE blockpoolID=BP-2054658932-192.168.102.133-1546499444184 layoutVersion=-63
其中,最主要的就是namespaceID,他是当前NN的惟一标识;
另一个则是clusterID,咱们查看其它节点的该文件能够发现,你们同属一个集群,那么clusterID则都相等;
再有,就是storageType字段,不一样类型的节点对应的不一样,例如当前这个文件是NN的,则其值就为namenode。查看其它节点的不一样类型storageType值,DN的则为DATA_NODE,而2NN的则和NN同样,都为NAME_NODE(毕竟帮NN作namenode最苦的活,是该获得相同的名分。)
Secondary NameNode用来监控HDFS状态的辅助后台程序,每隔一段时间获取HDFS元数据的快照。
在/opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary/current这个目录中查看SecondaryNameNode目录结构。
[root@h135 current]# pwd /opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary/current [root@h135 current]# ll 总用量 2280 -rw-r--r--. 1 root root 42 1月 3 23:58 edits_0000000000000000001-0000000000000000002 ... -rw-r--r--. 1 root root 42 1月 6 01:16 edits_0000000000000000191-0000000000000000192 -rw-r--r--. 1 root root 42 1月 6 02:16 edits_0000000000000000193-0000000000000000194 -rw-r--r--. 1 root root 1095 1月 6 01:16 fsimage_0000000000000000192 -rw-r--r--. 1 root root 62 1月 6 01:16 fsimage_0000000000000000192.md5 -rw-r--r--. 1 root root 1095 1月 6 02:16 fsimage_0000000000000000194 -rw-r--r--. 1 root root 62 1月 6 02:16 fsimage_0000000000000000194.md5 -rw-r--r--. 1 root root 208 1月 6 02:16 VERSION
显然,SecondaryNameNode的namesecondary/current目录和主namenode的current目录的布局相同。这样的好处在于:当主namenode发生故障时(假设没有及时备份数据),能够从SecondaryNameNode恢复数据。
咱们来实操一下方法一的结果。
一、在h133(NN)上杀死namenode守护进程,同时删除掉name目录,模拟比较完全的集群故障。
[root@h133 dfs]# kill -9 10392 [root@h133 dfs]# jps 14550 Jps 10520 DataNode 10684 NodeManager [root@h133 dfs]# pwd /opt/module/hadoop-2.7.2/data/tmp/dfs [root@h133 dfs]# rm -rf name/*
这时候咱们没法访问web,也没法执行任何业务操做(上传、文件)了。
二、接下来来到h135(2NN)上,执行拷贝操做:
[root@h135 dfs]# scp -r namesecondary/* root@h133:/opt/module/hadoop-2.7.2/data/tmp/dfs/name
三、在h133上单独启动namenode守护进程
root@h133 dfs]# hadoop-daemon.sh start namenode
等待namenode恢复状态,一切恢复如初。
模拟namenode故障,并采用方法二,恢复namenode数据
(1)修改hdfs-site.xml中的
<!-- 配置检查点的检查频率 --> <property> <name>dfs.namenode.checkpoint.period</name> <value>120</value> </property> <!-- 配置namenode的文件目录 --> <property> <name>dfs.namenode.name.dir</name> <value>/opt/module/hadoop-2.7.2/data/tmp/dfs/name</value> </property>
(2)kill -9 namenode进程
kill -9 xxxxx
(3)删除namenode存储的数据(/opt/module/hadoop-2.7.2/data/tmp/dfs/name)
rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/name/*
(4)若是SecondaryNameNode不和Namenode在一个主机节点上,须要将SecondaryNameNode存储数据的目录拷贝到Namenode存储数据的平级目录。
pwd /opt/module/hadoop-2.7.2/data/tmp/dfs ls data name namesecondary
(5)导入检查点数据(等待一会ctrl+c结束掉)
bin/hdfs namenode -importCheckpoint
(6)启动namenode
sbin/hadoop-daemon.sh start namenode
(7)若是提示文件锁了,能够删除in_use.lock
rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary/in_use.lock
Namenode启动时,首先将映像文件(fsimage)载入内存,并执行编辑日志(edits)中的各项操做。一旦在内存中成功创建文件系统元数据的映像,则建立一个新的fsimage文件和一个空的编辑日志。此时,namenode开始监听datanode请求。为了避免受到外部请求的干扰,namenode会运行在安全模式下,最直接的表现为:文件系统对于客户端来讲是只读的。
系统中的数据块的位置并非由namenode维护的,而是以块列表的形式存储在datanode中。在系统的正常操做期间,namenode会在内存中保留全部块位置的映射信息。在安全模式下,各个datanode会向namenode发送最新的块列表信息,namenode了解到足够多的块位置信息以后,便可高效运行文件系统。
若是知足“最小副本条件”,namenode会在30秒钟以后就退出安全模式。在启动一个刚刚格式化的HDFS集群时,由于系统中尚未任何块,因此namenode不会进入安全模式。可是若是是集群重启、故障恢复等从一个原有状态开始启动集群状态,则会启动安全模式,相信前面在模拟namenode故障时,您也有遇到安全模式。
最小副本条件:整个文件系统中99.9%的块知足最小副本级别(默认值:dfs.replication.min=1)。
集群处于安全模式,不能执行重要操做(写操做)。集群启动完成后,自动退出安全模式。关于安全模式的相关命令有:
(1)bin/hdfs dfsadmin -safemode get (功能描述:查看安全模式状态) (2)bin/hdfs dfsadmin -safemode enter (功能描述:进入安全模式状态) (3)bin/hdfs dfsadmin -safemode leave (功能描述:离开安全模式状态) (4)bin/hdfs dfsadmin -safemode wait (功能描述:等待安全模式状态)
一、查看安全模式状态
[root@h134 ~]# hdfs dfsadmin -safemode get Safe mode is OFF [root@h134 ~]# hadoop fs -put h134.txt put: `.': No such file or directory [root@h134 ~]# hadoop fs -put h134.txt / [root@h134 ~]# hadoop fs -cat /h134.txt this is h134 file.
当前状态为OFF,咱们能够正常的文件上传操做。
二、进入安全模式
[root@h134 ~]# hdfs dfsadmin -safemode enter Safe mode is ON [root@h134 ~]# hdfs dfsadmin -safemode get Safe mode is ON [root@h134 ~]# hadoop fs -put h134.txt / put: `/h134.txt': File exists [root@h134 ~]# hadoop fs -cat /h134.txt this is h134 file.
能够看到,进入安全模式以后,HDFS文件系统不支持咱们的写入操做,但支持读取操做。
三、离开安全模式
[root@h134 ~]# hdfs dfsadmin -safemode leave Safe mode is OFF
四、等待安全模式
这个模式,有点相似于消息队列的原理。当咱们执行一个任务时,能够等待队列有了充分的准备以后才执行咱们的任务。这里表现为:指定一个任务,安全模式关闭以后当即执行。
如今咱们编写一个shell脚本,简单的定义个上传文件的任务,在安全模式开启的状况下让其等待。要完成该需求,就可使用等待安全模式的命令。
[root@h134 ~]# vi wait_safe.sh #!/bin/bash echo "waiting for safe mode off..." hdfs dfsadmin -safemode wait echo "safe mode off, start upload file..." hadoop fs -put ~/h134.txt /user echo "upload done..."
接下来咱们使用xshell从新创建一个会话,用2个窗口来演示这个过程。
(1)会话一先开启集群的安全模式:
[root@h134 ~]# clear [root@h134 ~]# hdfs dfsadmin -safemode enter Safe mode is ON
(2)会话二执行任务脚本:
[root@h134 ~]# sh wait_safe.sh waiting for safe mode off...
能够看到,当前脚本阻塞在命令hdfs dfsadmin -safemode wait
上,正是咱们想要的效果。
(3)会话一离开安全模式
[root@h134 ~]# hdfs dfsadmin -safemode leave Safe mode is OFF
(4)立马切换到会话二的窗口:
[root@h134 ~]# sh wait_safe.sh waiting for safe mode off... Safe mode is OFF safe mode off, start upload file... upload done...
这样,就能在安全模式关闭的第一时间完成咱们的上传任务了。