DataNode BlockReport bug解决(二)

三、bug复现

       测试环境生成一个5M的测试文件,文件路径为/test/missdisk/part-m-0000,fsck查看了一下,该文件只有一个block,blockid为blk_1074399823_659259,该block的三个副本分别分布在5.42、5.26和5.27上面。

为了重现问题,选择5.26和5.27停掉DN,同时在5.42上面将将存放块blk_1074399823的盘data6下线。

       使用命令 echo “scsi remove-single-device 00 02 06 00″ > /proc/scsi/scsi

       

       查看5.42的DN日志,日志显示FsDatasetImpl移除data6盘,同时从FsDatasetImpl的数据结构中移除data6上面的所有副本信息,5.42会errorReport 将data6盘掉盘信息汇报给NN,NN记录下了。但是NN并没有将该盘上面的块信息从NN的数据结构blockmap中移除,由于5.26和5.27的DN停掉了,所以这个时候NN会从5.42上面仅存的副本(实际上已经坏了)repicate到其他两个节点上面去。当从5.42拷贝数据副本到其他节点时,实际上DN认为该副本其实已经损坏,并将块损坏了不能拷贝到其他节点上报给NN,最终副本拷贝失败。等待一段时间之后执行fsck,发现nn显示42节点副本是好的,但是get文件时报错。50070页面显示没有missing block,但是在Live Nodes页面对应的DN又有Failed Volumes。该问题成功重现。


四、解决方案

https://issues.apache.org/jira/browse/HDFS-7208?jql=project%20%3D%20HDFS%20AND%20text%20~%20errorReport

社区提出了解决这个问题的四种方案:

1、DN通过DatanodeProtocol.reportBadBlocks将坏盘中对应的数据块信息通知NN,让NN从数据结构中移除这些块信息。这种方式比较慢,因为每次只能上报一个block。

2、DN通过 DatanodeProtocol.errorReport将坏盘的storageId告诉给NN,从而让NN移除storageId下面所要的块信息,这种方式需要修改DatanodeProtocol.errorReport接口,增加storageId参数,同时DN端代码需要大量调整,比较麻烦。 

3、DN通过blockReport的方式告诉NN有坏盘,并从NN中移除坏盘中得数据块信息,由于blockReport每6小时才会执行一次block的全量汇报,这种方式会有很大的延迟。

4、DN通过心跳的方式告诉NN有坏盘,并从NN中移除坏盘中得数据块信息,社区提供的patch就是基于这种方式。这种方式不用只用修改NN端的代码。


Print Friendly

jiang yu

Leave a Reply