Hadoop HDFS DN 内核Bug

记录一个HDFS Bug,在Apache社区也有相关report,HDFS-7489,该Bug影响的版本是hadoop 2.5.0和hadoop 2.6.0,在hadoop 2.6.1进行了修复。

触发这个Bug的原因的磁盘的高IO与DataNode的相关锁机制,下面描述一下整个过程(由于过程比较复杂,下面简要说明)。

首先有两个DataNode 服务模块跟Bug相关,一个是BPOfferService,一个是DataXceiverServer。BPOfferService服务负责与NameNode的交互,比如register和heartbeat等;DataXceiverServer服务负责block数据的接收和发送。

当时hadoop101.dx这个DataNode的IO负载很高,从下图监控可以看到,有很高的IO WAIT。

 

这个时候该节点DataXceiverServer服务中的一个DataXceiver线程(block数据发送和接收的实际执行类)正在接收并写入数据,而很高的磁盘IO导致数据写入异常,发生异常被捕获,需要对异常进行处理。对异常的处理过程中,有一个check disk的步骤,即检查数据写入异常是否是磁盘导致,比如磁盘损坏或者数据目录的权限有问题。check disk是通过启动一个线程处理,处理的过程中有一个synchronized方法会持有FsVolumeList对象的锁,然后check所有数据盘的block finalized目录及其子目录的状态。由于该节点的磁盘IO很高,并且我们的数据盘有12块,每块的容量较大,单盘4T,这个check的过程会非常耗时间,也就是FsVolumeList对象的锁很长一段时间不会被释放。

与此同时,DataXceiverServer服务启动了另外一个DataXceiver线程来接收和传递其他的block,创建pipeline的过程需要获取FsDatasetImpl对象的锁,接下来需要创建block进行数据写入,这个过程需要持有FsVolumeList对象的锁,但是很不幸,FsVolumeList对象的锁正在被上面所说的check disk线程所持有。也就是说该DataXceiver线程需要一直等待对方释放。等待的同时,当然也就无法释放自己所持有的FsDatasetImpl对象的锁。

这样产生的效果就是接下来DataXceiverServer服务启动的所有DataXceiver线程都会等待FsDatasetImpl对象的锁,才可以创建pipeline。这时,该DataNode已经无法接受和发送数据。

更不幸的是,BPOfferService服务跟NameNode做heartbeat的时候,需要获取FsDatasetImpl对象的锁。结果就是BPOfferService服务也在等待对方锁的释放,无法正常heartbeat。一旦超时,NameNode就认为该DataNode已经dead。

解决方案:

其实这个Bug反应的核心问题是check disk的过程持有FsVolumeList这样的锁不合理的,会引起一系列连锁反应。社区的方案简单说来就是改造check disk相关方法的锁机制,也就是放弃锁住FsVolumeList对象,改用锁住不会影响到其他服务的对象。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值