1.NameNode与Secondary NameNode的工作机制
[1].第一阶段:namenode 启动
①.第一次启动 namenode 格式化后,创建 fsimage 和 edits 文件。如果不是第一次启
动,直接加载编辑日志和镜像文件到内存。
②.客户端对元数据进行增删改的请求。
③.namenode 记录操作日志,更新滚动日志。
④.namenode 在内存中对数据进行增删改查。
[2].第二阶段:Secondary NameNode 工作
①.Secondary NameNode 询问 namenode 是否需要 checkpoint。直接带回 namenode 是否检查结果。
②.Secondary NameNode 请求执行 checkpoint。
③namenode 滚动正在写的 edits 日志。
④.将滚动前的编辑日志和镜像文件拷贝到 Secondary NameNode。
⑤.Secondary NameNode 加载编辑日志和镜像文件到内存,并合并。
⑥.生成新的镜像文件 fsimage.chkpoint。
⑦.拷贝 fsimage.chkpoint 到 namenode。
⑧.namenode 将 fsimage.chkpoint 重新命名成 fsimage。
2.镜像文件和编辑日志文件
[1].namenode 被格式化之后,将在/opt/module/hadoop-2.7.2/data/tmp/dfs/name/current 目录中产生如下类型若干文件
edits_0000000000000000000
fsimage_0000000000000000000.md5
seen_txid
VERSION
①Fsimage 文件:HDFS 文件系统元数据的一个永久性的检查点,其中包含 HDFS文件系统的所有目录和文件 idnode 的序列化信息。
②Edits 文件:存放 HDFS 文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先会被记录到 edits 文件中。
③.seen_txid 文件保存的是一个数字,就是最后一个 edits_的数字
④.每次 Namenode 启动的时候都会将 fsimage 文件读入内存,并从 00001 开始到 seen_txid 中记录的数字依次执行每个 edits 里面的更新操作,保证内存中的元数据信息是最新的、同步的,可以看成 Namenode 启动的时候就将 fsimage 和 edits 文件进行了合并。
[2].其中edits文件和fsimage文件不能直接查看,其内容是序列化后的内容,只能用oiv和oev查看其内容
①.oiv apply the offline fsimage viewer to an fsimage
②.oev apply the offline edits viewer to an edits file
③.用法:hdfs oiv/oev -p 文件类型 -i 镜像文件 -o 转换后文件输出路径
[3].查看fsimage文件
①.生成xml:hdfs oiv -p XML -i fsimage_0000000000000000120 -o ./fsimage.xml
②.查看
<?xml version="1.0"?>
<fsimage>
<NameSection>
<genstampV1>1000</genstampV1>
<genstampV2>1014</genstampV2>
<genstampV1Limit>0</genstampV1Limit>
<lastAllocatedBlockId>1073741838</lastAllocatedBlockId>
<txid>120</txid>
</NameSection>
<INodeSection>
<lastInodeId>16403</lastInodeId>
<inode>
<id>16385</id>
<type>DIRECTORY</type>
<name></name>
<mtime>1547866929490</mtime>
<permission>w4xj:supergroup:rwxr-xr-x</permission>
<nsquota>9223372036854775807</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16386</id>
<type>DIRECTORY</type>
<name>user</name>
<mtime>1547866455990</mtime>
<permission>w4xj:supergroup:rwxr-xr-x</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16387</id>
<type>DIRECTORY</type>
<name>w4xj</name>
<mtime>1547869196317</mtime>
<permission>w4xj:supergroup:rwxr-xr-x</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16388</id>
<type>DIRECTORY</type>
<name>input</name>
<mtime>1547197140869</mtime>
<permission>w4xj:supergroup:rwxr-xr-x</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16389</id>
<type>FILE</type>
<name>wc.input</name>
<replication>3</replication>
<mtime>1547196366747</mtime>
<atime>1547345873892</atime>
<perferredBlockSize>134217728</perferredBlockSize>
<permission>w4xj:supergroup:rw-r--r--</permission>
<blocks>
<block>
<id>1073741825</id>
<genstamp>1001</genstamp>
<numBytes>37</numBytes>
</block>
</blocks>
</inode>
<inode>
<id>16390</id>
<type>FILE</type>
<name>hadoop-2.7.2.tar.gz</name>
<replication>3</replication>
<mtime>1547197140863</mtime>
<atime>1547954488776</atime>
<perferredBlockSize>134217728</perferredBlockSize>
<permission>w4xj:supergroup:rw-r--r--</permission>
<blocks>
<block>
<id>1073741826</id>
<genstamp>1002</genstamp>
<numBytes>134217728</numBytes>
</block>
<block>
<id>1073741827</id>
<genstamp>1003</genstamp>
<numBytes>63439959</numBytes>
</block>
</blocks>
</inode>
<inode>
<id>16399</id>
<type>FILE</type>
<name>hhh.txt</name>
<replication>1</replication>
<mtime>1547734846206</mtime>
<atime>1547734845602</atime>
<perferredBlockSize>134217728</perferredBlockSize>
<permission>w4xj:supergroup:rw-r--r--</permission>
<blocks>
<block>
<id>1073741836</id>
<genstamp>1012</genstamp>
<numBytes>2495</numBytes>
</block>
</blocks>
</inode>
<inode>
<id>16402</id>
<type>FILE</type>
<name>learnToLearn2.txt</name>
<replication>1</replication>
<mtime>1547866930286</mtime>
<atime>1547866929490</atime>
<perferredBlockSize>134217728</perferredBlockSize>
<permission>w4xj:supergroup:rw-r--r--</permission>
<blocks>
<block>
<id>1073741837</id>
<genstamp>1013</genstamp>
<numBytes>2495</numBytes>
</block>
</blocks>
</inode>
<inode>
<id>16403</id>
<type>FILE</type>
<name>learnToLearn11.txt</name>
<replication>3</replication>
<mtime>1547869196857</mtime>
<atime>1547952711996</atime>
<perferredBlockSize>134217728</perferredBlockSize>
<permission>w4xj:supergroup:rw-r--r--</permission>
<blocks>
<block>
<id>1073741838</id>
<genstamp>1014</genstamp>
<numBytes>2495</numBytes>
</block>
</blocks>
</inode>
</INodeSection>
<INodeReferenceSection></INodeReferenceSection>
<SnapshotSection>
<snapshotCounter>0</snapshotCounter>
</SnapshotSection>
<INodeDirectorySection>
<directory>
<parent>16385</parent>
<inode>16402</inode>
<inode>16386</inode>
</directory>
<directory>
<parent>16386</parent>
<inode>16387</inode>
</directory>
<directory>
<parent>16387</parent>
<inode>16399</inode>
<inode>16388</inode>
<inode>16403</inode>
</directory>
<directory>
<parent>16388</parent>
<inode>16390</inode>
<inode>16389</inode>
</directory>
</INodeDirectorySection>
<FileUnderConstructionSection></FileUnderConstructionSection>
<SnapshotDiffSection>
<diff>
<inodeid>16385</inodeid>
</diff>
</SnapshotDiffSection>
<SecretManagerSection>
<currentId>0</currentId>
<tokenSequenceNumber>0</tokenSequenceNumber>
</SecretManagerSection>
<CacheManagerSection>
<nextDirectiveId>1</nextDirectiveId>
</CacheManagerSection>
</fsimage>
[3].查看edits文件
①.生成xml:hdfs oev -p XML -i edits_0000000000000000114-0000000000000000117 -o ./edits.xml
②.查看
<?xml version="1.0" encoding="UTF-8"?>
<EDITS>
<EDITS_VERSION>-63</EDITS_VERSION>
<RECORD>
<OPCODE>OP_START_LOG_SEGMENT</OPCODE>
<DATA>
<TXID>114</TXID>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_TIMES</OPCODE>
<DATA>
<TXID>115</TXID>
<LENGTH>0</LENGTH>
<PATH>/user/w4xj/learnToLearn11.txt</PATH>
<MTIME>-1</MTIME>
<ATIME>1547952711996</ATIME>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_TIMES</OPCODE>
<DATA>
<TXID>116</TXID>
<LENGTH>0</LENGTH>
<PATH>/user/w4xj/input/hadoop-2.7.2.tar.gz</PATH>
<MTIME>-1</MTIME>
<ATIME>1547954488776</ATIME>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_END_LOG_SEGMENT</OPCODE>
<DATA>
<TXID>117</TXID>
</DATA>
</RECORD>
</EDITS>
3.滚动编辑日志
[1].正常情况 HDFS 文件系统有更新操作时,就会滚动编辑日志。也可以用命令强制滚动编辑日志。
[2].滚动编辑日志(前提必须启动集群)
hdfs dfsadmin -rollEdits
[3].Namenode 启动时加载镜像文件和编辑日志
4.Namenode 版本号 号
[1].查看 namenode 版本号
在/opt/module/hadoop-2.7.2/data/tmp/dfs/name/current 这个目录下查看 VERSION
namespaceID=1933630176
clusterID=CID-1f2bf8d1-5ad2-4202-af1c-6713ab381175
cTime=0
storageType=NAME_NODE
blockpoolID=BP-97847618-192.168.10.102-1493726072779
layoutVersion=-63
[2].namenode 版本号具体解释
①.namespaceID 在 HDFS 上,会有多个 Namenode,所以不同 Namenode 的namespaceID 是不同的,分别管理一组 blockpoolID。
②.clusterID 集群 id,全局唯一
③.cTime 属性标记了 namenode 存储系统的创建时间,对于刚刚格式化的存储系统,这个属性为 0;但是在文件系统升级之后,该值会更新到新的时间戳。
④.storageType 属性说明该存储目录包含的是 namenode 的数据结构。
⑤.blockpoolID:一个 block pool id 标识一个 block pool,并且是跨集群的全局唯一。当一个新的 Namespace 被创建的时候(format 过程的一部分)会创建并持久化一个唯一 ID。在创建过程构建全局唯一的 BlockPoolID 比人为的配置更可靠一些。NN 将BlockPoolID 持久化到磁盘中,在后续的启动过程中,会再次 load 并使用。
⑥.layoutVersion 是一个负整数。通常只有 HDFS 增加新特性时才会更新这个版本号。
5.web 端访问 SecondaryNameNode
http://node204:50090/status.html
6.chkpoint 检查时间参数设置[hdfs-default.xml],新增修改在[hdfs-site.xml],修改后要同步配置文件到其他节点
[1].通常情况下,SecondaryNameNode 每隔一小时执行一次。
<property>
<name>dfs.namenode.checkpoint.period</name>
<value>3600</value>
</property>
[2].一分钟检查一次操作次数,当操作次数达到 1 百万时,SecondaryNameNode 执行一次。
<property>
<name>dfs.namenode.checkpoint.txns</name>
<value>1000000</value>
<description>操作动作次数</description>
</property>
<property>
<name>dfs.namenode.checkpoint.check.period</name>
<value>60</value>
<description> 1 分钟检查一次操作次数</description>
</property>
7.SecondaryNameNode 目录结构
[1].Secondary NameNode 用来监控 HDFS 状态的辅助后台程序,每隔一段时间获取 HDFS元数据的快照。
[2].在 /opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary/current 这个目录中查看SecondaryNameNode 目录结构。
edits_0000000000000000001-0000000000000000002
fsimage_0000000000000000002
fsimage_0000000000000000002.md5
VERSION
[3].SecondaryNameNode 的 namesecondary/current 目录和主 namenode 的 current 目录的布局相同。
[4].好处 :在主namenode发生故障时( 假设没有及时备份数据),可以从SecondaryNameNode 恢复数据
8.namenode故障处理方式
[1].方法一:将 SecondaryNameNode 中数据拷贝到 namenode 存储数据的目录
①.kill -9 namenode 进程
②..删除 namenode 存储的数据(/opt/module/hadoop-2.7.2/data/tmp/dfs/name)
rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/name/*
③.拷贝 SecondaryNameNode 中数据到原 namenode 存储数据目录
scp -r w4xj@node04:/opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary/* ./name/
④.重新启动 namenode
sbin/hadoop-daemon.sh start namenode
[2].方法二:使用-importCheckpoint 选 项 启 动 namenode 守 护 进 程 ,从而将SecondaryNameNode 中数据拷贝到 namenode 目录中。
①.修改 hdfs-site.xml 中的
<property>
<name>dfs.namenode.checkpoint.period</name>
<value>120</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/opt/module/hadoop-2.7.2/data/tmp/dfs/name</value>
</property>
②.kill -9 namenode 进程
③.删除 namenode 存储的数据(/opt/module/hadoop-2.7.2/data/tmp/dfs/name)
rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/name/*
④. 如 果 SecondaryNameNode 不 和 Namenode 在 一 个 主 机 节 点 上 , 需 要 将SecondaryNameNode 存储数据的目录拷贝到 Namenode 存储数据的平级目录,并删除in_use.lock 文件。
scp -r w4xj@node204:/opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary ./
rm -rf in_use.lock
pwd
/opt/module/hadoop-2.7.2/data/tmp/dfs
ls
data name namesecondary
⑤.导入检查点数据(等待一会 ctrl+c 结束掉)
bin/hdfs namenode -importCheckpoint
⑥.启动 namenode
sbin/hadoop-daemon.sh start namenode
9.集群安全模式操作
[1].Namenode 启动时,首先将映像文件(fsimage)载入内存,并执行编辑日志(edits)中的各项操作。一旦在内存中成功建立文件系统元数据的映像,则创建一个新的 fsimage 文件和一个空的编辑日志。此时,namenode 开始监听 datanode 请求。但是此刻,namenode 运行在安全模式,即 namenode 的文件系统对于客户端来说是只读的。系统中的数据块的位置并不是由 namenode 维护的,而是以块列表的形式存储在datanode 中。在系统的正常操作期间,namenode 会在内存中保留所有块位置的映射信息。在安全模式下,各个 datanode 会向 namenode 发送最新的块列表信息,namenode 了解到足够多的块位置信息之后,即可高效运行文件系统。如果满足“最小副本条件”,namenode 会在 30 秒钟之后就退出安全模式。所谓的最小副本 条 件 指 的 是 在 整 个 文 件 系 统 中 99.9% 的 块 满 足 最 小 副 本 级 别 ( 默 认 值 :dfs.replication.min=1)。在启动一个刚刚格式化的 HDFS 集群时,因为系统中还没有任何块,所以 namenode 不会进入安全模式。
[2].基本语法
bin/hdfs dfsadmin -safemode get (功能描述:查看安全模式状态)
bin/hdfs dfsadmin -safemode enter (功能描述:进入安全模式状态)
bin/hdfs dfsadmin -safemode leave (功能描述:离开安全模式状态)
bin/hdfs dfsadmin -safemode wait (功能描述:等待安全模式状态)
[3].案例
①.先进入安全模式
bin/hdfs dfsadmin -safemode enter
②.执行下面的脚本
#!/bin/bash
bin/hdfs dfsadmin -safemode wait
bin/hdfs dfs -put ~/hello.txt /root/hello.txt
③.再打开一个窗口,执行
bin/hdfs dfsadmin -safemode leave
10.Namenode 多目录配置
[1].namenode 的本地目录可以配置成多个,且每个目录存放内容相同,增加了可靠性。
[2].在 hdfs-site.xml 文件中增加如下内容
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///${hadoop.tmp.dir}/dfs/name1,file:///${hadoop.tmp.dir}/dfs/name2</v
alue>
</property>
[3].停止集群,删除 data 和 logs 中所有数据。
rm -rf data/ logs/
[4].格式化集群并启动。
bin/hdfs namenode –format
sbin/start-dfs.sh
[5].查看结果