hadoop(2.5,2.6) HDFS偶发性心跳异常以及大量DataXceiver线程被Blocked故障处理分享
一、概要
公司近期Storm清洗程序那边反应HDFS会出现偶发性的异常导致数据写不进HDFS,另外一些Spark作业在大规模往HDFS灌数据时客户端会出现各种“all datanode bad..”以及服务端出现各种timeout,值得注意的是出现这样的问题是各个datanode节点的负载并不高!
二、故障分析
首先,当我们在HDFS客户端看到各种timeOut...什么waiting for reading等信息的时候,我们第一反应是为什么在往HDFS写数据时组成pipeline的各个datanode接收不到上游datanode的packet?这时候往往有人会说增加什么与客户端的超时时间,这个是肯定不行的(因为各个节点的负载非常低)。另外,如果出现“All datanode bad..”这种错误,我们往往会最先蹦出2种想法,第一:所有datanode都无法提供服务了,第二:dfsClient与hdfs服务端的DataXServer线程连接但是长时间没有packet传输而导致hdfs服务端启动保护机制自动断开,最终导致。
对于现在“All datanode bad..”这种问题,我基本可以排除第二种情况。再往下看,在平台监控系统中观察datanode的Thread Dump信息以及心跳信息,发现问题了:
重现异常情况,观察所有datanode的Thread Dump和心跳情况:
这个非常恐怖,心跳达到30s!!
更进一步分析,直接重现谷中,用jstack -l 命令看datanode具体的Thread Dump信息发现系统高密度调用FsDataSetImp中createTemporary和checkDirs方法:
由于上面频发调用在粗粒度对象锁FsDatasetImpl作用下的方法,导致发送心跳以及DataXceiver线程被blocked掉(因为他们同样在粗粒度对象锁FsDatasetImpl作用下),看Thread Dump信息,DataNode处理请求的DataXceiver线程被blocked:
发送心跳线程被blocked掉:
对于发送心跳的线程被blocked掉,从源码的看来主要是由于datanode向namenode发送心跳需要获得所在节点的资源相关情况,心跳通过getDfUsed,getCapacity,getAvailable,getBlockPoolUsed等方法获得(看FsDatasetImpl代码):
而这几个方法又是在FsDatasetImpl对象锁的作用范围下,因此心跳线程被blocked掉,具体看下getDfsUsed源码:
通过上面一轮的分析,基本可以分析故障原因:大规模往hdfs同时写多批文件,Datanode Thread Dump大量DataXceiver和发送心跳线程被Blocked掉,出现心跳异常有时候达到几十秒左右,大量DataXceiver线程被blocked掉无法向各个dfsClient的dataStreamer(向datanode发送packet)和ResponseProcessor(接收pipeline中datanode的ack)线程提供服务和datanode的BlockReceiver线程无法正常工作,最终导致客户端出现timeOut,或者dfsClient往hdfs写packet时整个PipeLine中的datanode无法响应客户端请求,进而系统内部启动pipeline容错,但是各个datanode都由于DataXceiver大量被Blocked掉无法提供服务,最后导致客户端报出“All dataNode are bad....”和服务端的timoeut。
换句话来说这个是HDFS中的一个大BUG。
这个是hadoop2.6中的bug,代码中采用了非常大粒度的对象锁(FsDatasetImpl),在大规模写操作时导致锁异常。这个bug出现在2.5和2.6这2个版本中(我们新集群用的是2.6),目前这个bug已经在2.6.1和2.7.0这2个版本中修复。官方具体给出的Patch信息:
https://issues.apache.org/jira/browse/HDFS-7489
https://issues.apache.org/jira/browse/HDFS-7999
其实具体的修复方案就是将这个大粒度的对象锁分解为多个小粒度的锁,并且将datande向namenode发送心跳线程从相关联的锁中剥离。
为了进一步确认,这是hadoop2.6中一个bug,我通过将测试集群升级到2.7.1(bug修复版本),对比2.7.1bug修复版本在大规模写多批文件时的datanode心跳线程以及DataXceiver线程的blocked以及心跳间隔情况。下面是hadoop2.7.1表现情况:
通过大规模往hdfs写多批文件,测试集群升级到hadoop2.7.1后,客户端没有报timeout和“All datanode bad...”异常,服务端也没有报timeOut异常。另外,通过和上文hadoop2.6.1中图表展示对比,发现这个bug在2.7.1得到了解决。
三、故障处理
这个故障对我们现有业务的影响大概有:
a、影响某个时间点通过storm写入hdfs的数据
b、作业提交时间点刚刚好遇到这个hdfs异常触发点时,会导致作业附属文件无法上传至hdfs最终导致作业提交失败.
c、如果hdfs这个异常点中时间拉长,可能会导致MR作业的的容错触发次数超过3次,最终导致作业失败。
具体处理方案:在不停机的情况下采用平滑升级至hadoop2.7.1版本
具体的升级步骤按照http://hadoop.apache.org/docs/r2.6.0/hadoop-project-dist/hadoop-hdfs/HdfsRollingUpgrade.html来就ok。
- hadoop(2.5,2.6) HDFS偶发性心跳异常以及大量DataXceiver线程被Blocked故障处理分享
- 掌握GCD以及后台永久运行的代码 (使用GCD处理后台线程和UI线程的交互)
- Hadoop中CombineFileInputFormat详解——处理大量小文件
- hadoop编程小技巧(6)---处理大量小数据文件CombineFileInputFormat应用
- Hadoop 2.6 在MAC YOSEMITE 上安装配置 以及开发环境eclipse搭建(一)
- hadoop作业分片处理以及任务本地性分析(源码分析第一篇) 推荐
- python爬虫进阶(十):日志系统、守护线程以及验证码处理
- 基于WeX5开发“终端故障处理云平台”分享
- 模拟MBR故障以及处理
- 【分享】通过Excel生成批量SQL语句,处理大量数据的好办法
- boost中asio网络库多线程并发处理实现,以及asio在多线程模型中线程的调度情况和线程安全。
- hadoop2.5发布:最新编译 32位、64位安装、源码包、API以及新特性
- Squid2.5-2.6的改进以及反向代理实现Web缓存加速
- Hadoop关于处理大量小文件的问题和解决方法
- 基于Hadoop的云盘系统上传和下载效率优化及处理大量小文件的解决方法
- DB2数据库内存耗尽故障处理经验分享
- Hadoop关于处理大量小文件的问题和解决方法
- hadoop面对大量的小文件处理
- Hadoop-2.6.2 HA + Federation 生产环境集群搭建实例以及源码编译案例分享
- python2.6升级2.7的方法及升级后的故障处理