一、NN和2NN工作机制
思考:NameNode 中的元数据是存储在哪里的?
首先,我们做个假设,如果存储在 NameNode 节点的磁盘中,因为经常需要进行随机访
问,还有响应客户请求,必然是效率过低。因此,元数据需要存放在内存中。但如果只存在
内存中,一旦断电,元数据丢失,整个集群就无法工作了。因此产生在磁盘中备份元数据的
FsImage。
这样又会带来新的问题,当在内存中的元数据更新时,如果同时更新 FsImage,就会导
致效率过低,但如果不更新,就会发生一致性问题,一旦 NameNode 节点断电,就会产生数
据丢失。因此,引入 Edits 文件(只进行追加操作,效率很高)。每当元数据有更新或者添加元
数据时,修改内存中的元数据并追加到 Edits 中。这样,一旦 NameNode 节点断电,可以通
过 FsImage 和 Edits 的合并,合成元数据。
但是,如果长时间添加数据到 Edits 中,会导致该文件数据过大,效率降低,而且一旦
断电,恢复元数据需要的时间过长。因此,需要定期进行 FsImage 和 Edits 的合并,如果这
个操作由 NameNode 节点完成,又会效率过低。因此,引入一个新的节点 SecondaryNamenode,
专门用于 FsImage 和 Edits 的合并。
工作机制如下图:
第一阶段:NameNode启动
第一次启动 NameNode 格式化后,创建 Fsimage 和 Edits 文件。如果不是第一次启 动,直接加载编辑日志和镜像文件到内存。
客户端对元数据进行增删改的请求。
NameNode 记录操作日志,更新滚动日志。
NameNode 在内存中对数据进行增删改
第二阶段: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。
NN 和 2NN 详解
Fsimage:NameNode 内存中元数据序列化后形成的文件。Edits:记录客户端更新元数据信息的每一步操作(可通过 Edits 运算出元数据)。NameNode 启动时,先滚动 Edits 并生成一个空的 edits.inprogress,然后加载 Edits 和 Fsimage到内存中,此时 NameNode 内存就持有最新的元数据信息。Client 开始对 NameNode 发送 元数据的增删改的请求,这些请求的操作首先会被记录到 edits.inprogress 中(查询元数据 的操作不会被记录在 Edits中,因为查询操作不会更改元数据信息),如果此时 NameNode 挂掉,重启后会从 Edits 中读取元数据的信息。然后,NameNode 会在内存中执行元数据 的增删改的操作。由于 Edits 中记录的操作会越来越多,Edits 文件会越来越大,导致 NameNode 在启动加载 Edits 时会很慢,所以需要对 Edits 和 Fsimage 进行合并(所谓合并,就是将 Edits 和 Fsimage 加载到内存中,照着 Edits 中的操作一步步执行,最终形成新的 Fsimage)。 SecondaryNameNode 的作用就是帮助NameNode 进行 Edits 和 Fsimage 的合并工作。 SecondaryNameNode 首先会询问 NameNode是否需要 CheckPoint(触发 CheckPoint 需要 满足两个条件中的任意一个,定时时间到和 Edits中数据写满了)。直接带回 NameNode 是否检查结果。SecondaryNameNode 执行 CheckPoint 操作,首先会让 NameNode 滚动 Edits 并生成一个空的 edits.inprogress,滚动 Edits 的目的是给Edits 打个标记,以后所有新的操 作都写入 edits.inprogress,其他未合并的 Edits 和 Fsimage会拷贝到 SecondaryNameNode 的本地,然后将拷贝的 Edits 和 Fsimage 加载到内存中进行合并,生成 fsimage.chkpoint, 然后将 fsimage.chkpoint 拷贝给 NameNode,重命名为 Fsimage后替换掉原来的 Fsimage。 NameNode 在启动时就只需要加载之前未合并的 Edits 和 Fsimage 即可,因为合并过的 Edits 中的元数据信息已经被记录在 Fsimage 中。
二、Fsimage 和 Edits解析
1、Fsimage 和 Edits概念
NameNode被格式化之后,将在 /opt/module/hadoop-2.7.2/data/tmp/dfs/name/current (core-hdfs.xml中配置的) 目录中产生如下文件:
fsimage_0000000000000000000fsimage_0000000000000000000.md5seen_txidVERSION
- Fsimage文件:HDFS文件系统元数据的一个永久性的检查点,其中包含HDFS文件系统的所有目录和文件inode的序列化信息。
Edits文件:存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先会被记录到Edits文件中。
seentxid文件保存的是一个数字,就是最后一个edits的数字
- 每次NameNode启动的时候都会将Fsimage文件读入内存,加载Edits里面的更新操作,保证内存中的元数据信息是最新的、同步的,可以看成NameNode启动的时候就将Fsimage和Edits文件进行了合并
2、oiv 查看 Fsimage 文件
2.1、查看ovi命令
$ hdfsoiv apply the offline fsimage viewer to an fsimageoev apply the offline edits viewer to an edits file
2.2、基本语法
$ hdfs oiv -p 文件类型 -i 镜像文件 -o 转换后文件输出路径
2.3、实例操作
$ hdfs oiv -p XML -i fsimage_0000000000000000025 -o /opt/module/hadoop-2.7.2/fsimage.xml
将显示的 xml 文件内容格式化,即可看见client的操作日志;
3、oev 查看 Edits 文件
3.1、基本语法
$ hdfs oev -p 文件类型 -i 编辑日志 -o 转换后文件输出路径
3.2、实例操作
$ hdfs oev -p XML -i edits_0000000000000000012-0000000000000000013 -o /opt/module/hadoop-2.7.2/edits.xml
将显示的 xml 文件内容格式化,即可看见client的操作日志;
三、2NN CheckPoint设置
- 通常情况下,SecondaryNameNode 每隔一小时执行一次
[hdfs-default.xml]
<property><name>dfs.namenode.checkpoint.period</name><value>3600</value></property>
- 一分钟检查一次操作次数,当操作次数达到 1 百万时,SecondaryNameNode 执
行一次
```xml
dfs.namenode.checkpoint.txns 1000000 操作动作次数
<a name="Jiwgh"></a>
# 四、NN故障处理
NameNode 故障后,可以采用如下两种方法恢复数据:
<a name="2OyZl"></a>
## 4.1、将 SecondaryNameNode 中数据拷贝到 NameNode 存储数据的目录
- kill -9 NameNode 进程<br />
- 删除 NameNode 存储的数据(/opt/module/hadoop-2.7.2/data/tmp/dfs/name)bash
$ rm -rf /opt/module/hadoop- 2.7.2/data/tmp/dfs/name/
- 拷贝 SecondaryNameNode 中数据到原 NameNode 存储数据目录bash
$ scp -r name@hadoop104:/opt/module/hadoop- 2.7.2/data/tmp/dfs/namesecondary/ ./name/
- 重新启动 NameNodebash
$ sbin/hadoop-daemon.sh start namenode
<a name="PHM6l"></a>
## 4.2、使用-importCheckpoint 选项启动 NameNode 守护进程,从而将SecondaryNameNode 中数据拷贝到 NameNode 目录中。
- 修改 hdfs-site.xml 中的配置xml
- kill -9 NameNode 进程- 删除 NameNode 存储的数据(/opt/module/hadoop-2.7.2/data/tmp/dfs/name)```bash$ rm -rf /opt/module/hadoop- 2.7.2/data/tmp/dfs/name/*
- 如果 SecondaryNameNode 和 NameNode 不在一个主机节点上,需要将SecondaryNameNode 存储数据的目录拷贝到 NameNode 存储数据的平级目录,并删除 in_use.lock 文件
$ scp -r atguigu@hadoop104:/opt/module/hadoop- 2.7.2/data/tmp/dfs/namesecondary ./$ rm -rf in_use.lock
- 导入检查点数据(等待一会 ctrl+c 结束掉)
$ bin/hdfs namenode -importCheckpoint
- 重新启动 NameNode
$ sbin/hadoop-daemon.sh start namenode
<br />
