一、NN和2NN工作机制

思考:NameNode 中的元数据是存储在哪里的?
首先,我们做个假设,如果存储在 NameNode 节点的磁盘中,因为经常需要进行随机访
问,还有响应客户请求,必然是效率过低。因此,元数据需要存放在内存中。但如果只存在 内存中,一旦断电,元数据丢失,整个集群就无法工作了。因此产生在磁盘中备份元数据的 FsImage。
这样又会带来新的问题,当在内存中的元数据更新时,如果同时更新 FsImage,就会导 致效率过低,但如果不更新,就会发生一致性问题,一旦 NameNode 节点断电,就会产生数 据丢失。因此,引入 Edits 文件(只进行追加操作,效率很高)。每当元数据有更新或者添加元 数据时,修改内存中的元数据并追加到 Edits 中。这样,一旦 NameNode 节点断电,可以通 过 FsImage 和 Edits 的合并,合成元数据。
但是,如果长时间添加数据到 Edits 中,会导致该文件数据过大,效率降低,而且一旦 断电,恢复元数据需要的时间过长。因此,需要定期进行 FsImage 和 Edits 的合并,如果这 个操作由 NameNode 节点完成,又会效率过低。因此,引入一个新的节点 SecondaryNamenode, 专门用于 FsImage 和 Edits 的合并。
工作机制如下图:

image.png

第一阶段: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 详解

  1. Fsimage:NameNode 内存中元数据序列化后形成的文件。
  2. Edits:记录客户端更新元数据信息的每一步操作(可通过 Edits 运算出元数据)。
  3. NameNode 启动时,先滚动 Edits 并生成一个空的 edits.inprogress,然后加载 Edits Fsimage
  4. 到内存中,此时 NameNode 内存就持有最新的元数据信息。Client 开始对 NameNode 发送 元数据的增删改
  5. 的请求,这些请求的操作首先会被记录到 edits.inprogress 中(查询元数据 的操作不会被记录在 Edits
  6. 中,因为查询操作不会更改元数据信息),如果此时 NameNode 挂掉,重启后会从 Edits 中读取元数据的信息。
  7. 然后,NameNode 会在内存中执行元数据 的增删改的操作。
  8. 由于 Edits 中记录的操作会越来越多,Edits 文件会越来越大,导致 NameNode 在启动加载 Edits 时会
  9. 很慢,所以需要对 Edits Fsimage 进行合并(所谓合并,就是将 Edits Fsimage 加载到内存中,
  10. 照着 Edits 中的操作一步步执行,最终形成新的 Fsimage)。 SecondaryNameNode 的作用就是帮助
  11. NameNode 进行 Edits Fsimage 的合并工作。 SecondaryNameNode 首先会询问 NameNode
  12. 是否需要 CheckPoint(触发 CheckPoint 需要 满足两个条件中的任意一个,定时时间到和 Edits
  13. 中数据写满了)。直接带回 NameNode 是否检查结果。SecondaryNameNode 执行 CheckPoint 操作,
  14. 首先会让 NameNode 滚动 Edits 并生成一个空的 edits.inprogress,滚动 Edits 的目的是给
  15. Edits 打个标记,以后所有新的操 作都写入 edits.inprogress,其他未合并的 Edits Fsimage
  16. 会拷贝到 SecondaryNameNode 的本地,然后将拷贝的 Edits Fsimage 加载到内存中进行合并,
  17. 生成 fsimage.chkpoint 然后将 fsimage.chkpoint 拷贝给 NameNode,重命名为 Fsimage
  18. 后替换掉原来的 Fsimage NameNode 在启动时就只需要加载之前未合并的 Edits Fsimage 即可,
  19. 因为合并过的 Edits 中的元数据信息已经被记录在 Fsimage 中。

二、Fsimage 和 Edits解析

1、Fsimage 和 Edits概念

NameNode被格式化之后,将在 /opt/module/hadoop-2.7.2/data/tmp/dfs/name/current (core-hdfs.xml中配置的) 目录中产生如下文件:

  1. fsimage_0000000000000000000
  2. fsimage_0000000000000000000.md5
  3. seen_txid
  4. VERSION
  • Fsimage文件:HDFS文件系统元数据的一个永久性的检查点,其中包含HDFS文件系统的所有目录和文件inode的序列化信息。
  • Edits文件:存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先会被记录到Edits文件中。

  • seentxid文件保存的是一个数字,就是最后一个edits的数字

  • 每次NameNode启动的时候都会将Fsimage文件读入内存,加载Edits里面的更新操作,保证内存中的元数据信息是最新的、同步的,可以看成NameNode启动的时候就将Fsimage和Edits文件进行了合并

2、oiv 查看 Fsimage 文件

2.1、查看ovi命令

  1. $ hdfs
  2. oiv apply the offline fsimage viewer to an fsimage
  3. oev apply the offline edits viewer to an edits file

2.2、基本语法

  1. $ hdfs oiv -p 文件类型 -i 镜像文件 -o 转换后文件输出路径

2.3、实例操作

  1. $ hdfs oiv -p XML -i fsimage_0000000000000000025 -o /opt/module/hadoop-2.7.2/fsimage.xml

将显示的 xml 文件内容格式化,即可看见client的操作日志;

3、oev 查看 Edits 文件

3.1、基本语法

  1. $ hdfs oev -p 文件类型 -i 编辑日志 -o 转换后文件输出路径

3.2、实例操作

  1. $ 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]

  1. <property>
  2. <name>dfs.namenode.checkpoint.period</name>
  3. <value>3600</value>
  4. </property>
  • 一分钟检查一次操作次数,当操作次数达到 1 百万时,SecondaryNameNode 执 行一次 ```xml dfs.namenode.checkpoint.txns 1000000 操作动作次数
dfs.namenode.checkpoint.check.period 60 1分钟检查一次操作次数 <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 dfs.namenode.checkpoint.period 120

dfs.namenode.name.dir /opt/module/hadoop-2.7.2/data/tmp/dfs/name

  1. - kill -9 NameNode 进程
  2. - 删除 NameNode 存储的数据(/opt/module/hadoop-2.7.2/data/tmp/dfs/name)
  3. ```bash
  4. $ rm -rf /opt/module/hadoop- 2.7.2/data/tmp/dfs/name/*
  • 如果 SecondaryNameNode 和 NameNode 不在一个主机节点上,需要将SecondaryNameNode 存储数据的目录拷贝到 NameNode 存储数据的平级目录,并删除 in_use.lock 文件
  1. $ scp -r atguigu@hadoop104:/opt/module/hadoop- 2.7.2/data/tmp/dfs/namesecondary ./
  2. $ rm -rf in_use.lock
  • 导入检查点数据(等待一会 ctrl+c 结束掉)
  1. $ bin/hdfs namenode -importCheckpoint
  • 重新启动 NameNode
    1. $ sbin/hadoop-daemon.sh start namenode
  1. <br />