正文
经过前面两个步骤,主要的元数据被构建,HDFS的整个目录树被完整建立,但是并没有掌握数据块Block与DataNode之间的对应关系BlocksMap,甚至对DataNode的情况都不掌握,所以需要等待DataNode注册,并完成对从DataNode汇报上来的数据块汇总。待汇总的数据量达到预设比例(dfs.namenode.safemode.threshold-pct)后退出Safemode。
NameNode重启经过加载FSImage和回放EditLog后,所有DataNode不管进程是否发生过重启,都必须经过以下两个步骤:
-
DataNode重新注册RegisterDataNode;
-
DataNode汇报所有数据块BlockReport。
对于节点规模较大和元数据量较大的集群,这个阶段的耗时会非常可观。主要有三点原因:
-
处理BlockReport的逻辑比较复杂,相对其他RPC操作耗时较长。图5对比了BlockReport和AddBlock两种不同RPC的处理时间,尽管AddBlock操作也相对复杂,但是对比来看,BlockReport的处理时间显著高于AddBlock处理时间;
-
NameNode对每一个BlockReport的RPC请求处理都需要持有全局锁,也就是说对于BlockReport类型RPC请求实际上是串行处理;
-
NameNode重启时所有DataNode集中在同一时间段进行BlockReport请求。
之前我们在
NameNode内存全景
一文中详细描述过Block在NameNode元数据中的关键作用及与Namespace/DataNode/BlocksMap的复杂关系,从中也可以看出,每个新增Block需要维护多个关系,更何况重启过程中所有Block都需要建立同样复杂关系,所以耗时相对较高。
根据前面对NameNode重启过程的简单梳理,在各个阶段可以适当的实施优化以加快NameNode重启过程。
HDFS-7097
解决重启过程中SBN执行CheckPoint时不能处理BlockReport请求的问题
Fix:
2.7.0
Hadoop-2.7.0版本前,SBN(StandbyNameNode)在执行CheckPoint操作前会先获得全局读写锁fsLock,在此期间,BlockReport请求由于不能获得全局写锁会持续处于等待状态,直到CheckPoint完成后释放了fsLock锁后才能继续。NameNode重启的第三个阶段,同样存在这种情况。而且对于规模较大的集群,每次CheckPoint时间在分钟级别,对整个重启过程影响非常大。实际上,CheckPoint是对目录树的持久化操作,并不涉及BlocksMap数据结构,所以CheckPoint期间是可以让BlockReport请求直接通过,这样可以节省期间BlockReport排队等待带来的时间开销,
HDFS-7097
正是将锁粒度放小解决了CheckPoint过程不能处理BlockReport类型RPC请求的问题。
与
HDFS-7097
相对,另一种思路也值得借鉴,就是重启过程尽可能避免出现CheckPoint。触发CheckPoint有两种情况:时间周期或HDFS写操作事务数,分别通过参数dfs.namenode.checkpoint.period和dfs.namenode.checkpoint.txns控制,默认值分别是3600s和1,000,000,即默认情况下一个小时或者写操作的事务数超过1,000,000触发一次CheckPoint。为了避免在重启过程中频繁执行CheckPoint,可以适当调大dfs.namenode.checkpoint.txns,建议值10,000,000 ~ 20,000,000,带来的影响是EditLog文件累计的个数会稍有增加。从实践经验上看,对一个有亿级别元数据量的NameNode,回放一个EditLog文件(默认1,000,000写操作事务)时间在秒级,但是执行一次CheckPoint时间通常在分钟级别,综合权衡减少CheckPoint次数和增加EditLog文件数收益比较明显。
HDFS-6763
解决SBN每间隔1min全局计算和验证Quota值导致进程Hang住数秒的问题
Fix:
2.8.0
ANN(ActiveNameNode)将HDFS写操作实时写入JN的EditLog文件,为同步数据,SBN默认间隔1min从JN拉取一次EditLog文件并进行回放,完成后执行全局Quota检查和计算,当Namespace规模变大后,全局计算和检查Quota会非常耗时,在此期间,整个SBN的Namenode进程会被Hang住,以至于包括DN心跳和BlockReport在内的所有RPC请求都不能及时处理。NameNode重启过程中这个问题影响突出。
实际上,SBN在EditLog Tailer阶段计算和检查Quota完全没有必要,HDFS-6763将这段处理逻辑后移到主从切换时进行,解决SBN进程间隔1min被Hang住的问题。
从优化效果上看,对一个拥有接近五亿元数据量,其中两亿数据块的NameNode,优化前数据块汇报阶段耗时~30min,其中触发超过20次由于计算和检查Quota导致进程Hang住~20s的情况,整个BlockReport阶段存在超过5min无效时间开销,优化后可到~25min。
HDFS-7980
简化首次BlockReport处理逻辑优化重启时间
Fix:
2.7.1
NameNode加载完元数据后,所有DataNode尝试开始进行数据块汇报,如果汇报的数据块相关元数据还没有加载,先暂存消息队列,当NameNode完成加载相关元数据后,再处理该消息队列。对第一次块汇报的处理比较特别(NameNode重启后,所有DataNode的BlockReport都会被标记成首次数据块汇报),为提高处理速度,仅验证块是否损坏,之后判断块状态是否为FINALIZED,若是建立数据块与DataNode的映射关系,建立与目录树中文件的关联关系,其他信息一概暂不处理。对于非初次数据块汇报,处理逻辑要复杂很多,对报告的每个数据块,不仅检查是否损坏,是否为FINALIZED状态,还会检查是否无效,是否需要删除,是否为UC状态等等;验证通过后建立数据块与DataNode的映射关系,建立与目录树中文件的关联关系。
初次数据块汇报的处理逻辑独立出来,主要原因有两方面:
-
加快NameNode的启动时间;测试数据显示含~500M元数据的NameNode在处理800K个数据块的初次块汇报的处理时间比正常块汇报的处理时间可降低一个数量级;
-
启动过程中,不提供正常读写服务,所以只要确保正常数据(整个Namespace和所有FINALIZED状态Blocks)无误,无效和冗余数据处理完全可以延后到IBR(IncrementalBlockReport)或下次BR(BlockReport)。
这本来是非常合理和正常的设计逻辑,但是实现时NameNode在判断是否为首次数据块块汇报的逻辑一直存在问题,导致这段非常好的改进点逻辑实际上长期并未真正执行到,直到
HDFS-7980
在Hadoop-2.7.1修复该问题。
HDFS-7980
的优化效果非常明显,测试显示,对含80K Blocks的BlockReport RPC请求的处理时间从~500ms可优化到~100ms,从重启期整个BlockReport阶段看,在超过600M元数据,其中300M数据块的NameNode显示该阶段从~50min优化到~25min。
HDFS-7503
解决重启前大删除操作会造成重启后锁内写日志降低处理能力
Fix:
2.7.0
若NameNode重启前产生过大删除操作,当NameNode加载完FSImage并回放了所有EditLog构建起最新目录树结构后,在处理DataNode的BlockReport时,会发现有大量Block不属于任何文件,Hadoop-2.7.0版本前,对于这类情况的输出日志逻辑在全局锁内,由于存在大量IO操作的耗时,会严重拉长处理BlockReport的处理时间,影响NameNode重启时间。
HDFS-7503
的解决办法非常简单,把日志输出逻辑移出全局锁外。线上效果上看对同类场景优化比较明显,不过如果重启前不触发大的删除操作影响不大。
防止热备节点SBN(StandbyNameNode)/冷备节点SNN(SecondaryNameNode)长时间未正常运行堆积大量Editlog拖慢NameNode重启时间
选择HA热备方案SBN(StandbyNameNode)还是冷备方案SNN(SecondaryNameNode)架构,执行CheckPoint的逻辑几乎一致,如图6所示。如果SBN/SNN服务长时间未正常运行,CheckPoint不能按照预期执行,这样会积压大量EditLog。积压的EditLog文件越多,重启NameNode需要加载EditLog时间越长。所以尽可能避免出现SNN/SBN长时间未正常服务的状态。
在一个有500M元数据的NameNode上测试加载一个200K次HDFS事务操作的EditLog文件耗时~5s,按照默认2min的EditLog滚动周期,如果一周时间SBN/SNN未能正常工作,则会累积~5K个EditLog文件,此后一旦发生NameNode重启,仅加载EditLog文件的时间就需要~7h,也就是整个集群存在超过7h不可用风险,所以切记要保证SBN/SNN不能长时间故障。
HDFS-6425
HDFS-6772
NameNode重启后DataNode快速退出blockContentsStale状态防止PostponedMisreplicatedBlocks过大影响对其他RPC请求的处理能力