目录

HDFS的edits文件不连续导致NameNode无法启动的恢复方法

目录

NameNode启动时,会访问所有JournalNode去获取edits文件,最终结合JournalNode和本地NameNode所有的edits文件后,发现存在edits文件不连续时,会出现此错误。

There appears to be a gap in the edit log. We expected txid 138, but got txid 145.

/posts/20220918025644/71404a822c8444b6b2ca51b7c854e32e.png

/posts/20220918025644/1a6f88a374fa427eb898cdb6931d8985.png

还比如以下场景,fsimage的序号为120,但所有JournalNode的edits文件均没有121开头的,因此依然无法启动。

/posts/20220918025644/af73883723044d108f82b1ad67247a8a.png

这种情况下,除非借助外部备份恢复机制来恢复,否则环境上应该是找不到缺失的edits文件了。

这种场景下修复很大概率会存在丢失部分数据的风险。

使用HDFS的修复命令修复edits,实际上为自动从头遍历一次edits文件,当不存在时自动跳过,最终生成一份最新的fsimage文件,即可保证namenode正常启动。当edits文件比较多,数据量比较大时,会耗时较长:

1
hdfs namenode -recover -force

/posts/20220918025644/12973da52df641faacef75971ca30258.png

/posts/20220918025644/69fe5203ee1248f7b89bb06c83f492c5.png

从日志上可以看出流程:

  1. 读取最新的fsimage
  2. 读取所有JournalNode的edits文件
  3. 发现出gap
  4. -force参数自动选择了c,跳过缺失的edits文件继续回放edits文件
  5. 如果在其他JournalNode上找到了edits文件,则下载过来使用
  6. 直到所有edits文件都回放完成
  7. 生成最新的fsimage文件,并记录seen_txid

随后,我们正常启动NameNode与ZKFC即可。

另一NameNode节点若无法启动,可以使用以下命令,重新获取当前节点的最新的fsimage数据,然后就可以正常启动了。

1
hdfs namenode -bootstrapStandby -force -skipSharedEditsCheck

如果上诉的hdfs namenode -recover -force命令不好使,那么只能手动修复能让其成功启动,数据一样会存在丢失的风险。

  • 对比主备节点的NameNode数据,在找到连续的最新的edits文件和fsimage,在它之后的edits文件都手动删除。尽可能地保留到最新的数据。
  • 在该节点的NameNode中删除seen_txid文件
  • hdfs namenode -initializeSharedEdits -force将该节点的edits文件覆盖到所有JournalNode
  • 启动该NameNode与ZKFC
  • 另一NameNode节点执行hdfs namenode -bootstrapStandby -force -skipSharedEditsCheck重新拉取fsimage
  • 启动另一NameNode节点与ZKFC

不管哪个方式,启动后,很大概率会出现坏块等情况。使用hdfs fsck /扫描一下,如果出现了,那么只能删除了,基本没有挽救的余地hdfs fsck / -delete


当前发现HDFS 3.4.0之前的版本,会导致这个edit log出现gap的问题是这个issue HDFS-16689 :Standby NameNode crashes when transitioning to Active with in-progress tailer

启用dfs.ha.tail-edits.in-progress时,当发生主备倒换时,因网络情况可能会造成这个问题。对于老版本的规避方案是dfs.ha.tail-edits.in-progress配置为false或者删除此配置项,保持默认值false

最终合入的PR是:https://github.com/apache/hadoop/pull/4744/files

做法就是在主备倒换过程中的doTailEdits时,添加特殊场景判断,走回原来的逻辑,不回放in-progress的片段。而对于备机日常的doTailEdits时,继续保持使用in-progress的片段,得以实现读写分离时能加速备可用的特性。