概述
HDFS 默认以三副本存储文件 block,且三副本的选择遵循一定的策略,指导思想是尽量降低 block 丢失的风险。除此之外,NameNode 也会主动将副本数不足的 block 进行复制,以达到其目标副本数。在这样的重重保护下,文件 block 丢失的风险很低。但是,现网依然会间歇性地出现丢块问题,需要分析原因,并提出解决办法。
丢块原因分析
结合现网的多起丢块事故,基本可以看到,丢块的情况一般具备下面两个特征:
-
业务侧指定了低副本存储
例如现网有大量文件使用2副本存储。在2副本写入的情况下,按照 HDFS 客户端默认配置,一旦写入出现错误,客户端不会申请新的 DN 进行错误恢复,后续该 block 将保持为单副本写入(作为对比:在3副本写入的情况下,一但出错,客户端将及时申请新的 DN 进行错误恢复,以此来尽量保持为3副本写入)。 -
NN 侧不能及时为只剩单副本的 block 安排复制任务
这个地方是 NN 的一个缺陷,一旦触发这个缺陷,则会导致 NN 长时间不能为单副本的 block 安排复制任务(事实上这些 block 已经非常危险,应该尽快为它们安排复制任务),详细触发逻辑如下:- 对于只剩一个副本的 block,它的复制优先级是最高的,会加入到最高优先级队列中去(NN 一共有5个优先级队列,用于保存需要进行复制的 block)
- NN 周期性处理这个5个队列(从最高优先级开始,依次降低,周期默认为3s)。
- 最关键的是,为了防止低优先级队列被饿死,NN 维持了一个书签(bookmark) 功能,处理的时候,不会回头,而是一路往前,即:从最高优先级队列开始,单向车道一直往前,直到最低优先级处理完成之后,算是完整的一轮完成。然后再回过头来,从最高优先级队列继续开始。
- 在某些特殊情况下(例如不断出现坏盘,集群正在卸载 DN 等),NN 的低优先级队列里,不断会有新的 block 加进来,导致 NN 一直都忙于处理这些新加入的 block,没有机会回过头去处理那些紧急的高优先级 block。
处理方案
同样,需要从客户端侧和 NN 侧分别处理。
- 客户端侧
客户端侧需要配置以下选项,意为:无论客户端是几副本写入,只要出现错误,都必须申请新的 DN 进行错误恢复:
<property>
<name>dfs.client.block.write.replace-datanode-on-failure.policy</name>
<value>ALWAYS</value>
</property>
-
NN 侧
需要合入社区 patch HDFS-14861. Reset LowRedundancyBlocks Iterator periodically,解决高优 block 长时间无法被复制的问题,具体思路是:NN 引入一个 reset 机制,每隔2小时左右(可配置),不管当前还有多少低优的 block 等待处理,都强制 reset 一次,重新从高优 block 开始从头处理。 -
注意:DN 侧不用特意缩小全量 block report 间隔
DN 侧出现坏盘时,会立刻安排心跳线程向 NN 做一次全量 block report,目的是尽快上报副本损失情况,这是一次实时上报,不受制于 DN 配置的 block report 间隔,因此,不需要调整 DN 的 block report interval 配置。
网友评论