HDFS之Cannot obtain block length for LocatedBlock异常
昨天公司集群升级,采集平台的flume agent没有停,导致一些文件异常,无法读,也无法使用cp或者get命令,报Cannot obtain block length for LocatedBlock
。
首先使用fsck来检查下该文件,命令hdfs fsck file_path -files -blocks -locations
,提示如下:
1 | Status: HEALTHY |
现实文件依然是打开的,使用命令hadoop fsck file_path -openforwrite
查看目录下打开的文件,显示:
1 | 17/08/03 15:21:50 WARN ssl.FileBasedKeyStoresFactory: The property 'ssl.client.truststore.location' has not been set, no TrustStore will be loaded |
显示OPENFORWRITE
,也有MISSING
信息,推断应该是文件没有close成功。
之所以没有关成功,通过看flume的log发现集群是safemode状态,无法close成功,flume catch住异常之后只是抛出了个WARN,设置failedToClose
为true,然后继续执行代码进行rename操作,rename操作没有成功被放到一个线程中不断的去尝试rename,等集群恢复之后,rename成功了。
下面就是怎么恢复文件,文件是打开状态是因为namenode依然记录这该文件的租约,该租约没有被关闭,使用appendToFile命令检验下
1 | // 这个命令执行之后,允许在窗体中输入字符串,Ctrl + C退出stdin,此后stdin数据将会追加到hdfs文件中。 |
租约冲突了,确认租约没有关闭。
在hdfs官网上查看hdfs有恢复租约的命令,hdfs debug recoverLease -path
,但是在2.7版本以后才有,昨天集群升级到了2.7.3,但是坑的是客户端没有升级依然是老版的,没有这个命令。
(让Hadoop运维给执行下debug命令居然让我把损坏的文件删掉。。。)只好自己装个2.7.3的客户端了,然后执行recoverLease命令之后,文件恢复正常。
批量处理命令
1 | hadoop fsck /file_path -openforwrite | egrep -v '^\.+$' | egrep "MISSING|OPENFORWRITE" | grep -o "/[^ ]*" | sed -e "s/:$//" | xargs -i hdfs debug recoverLease -path {} |
为什么会出现租约没有关闭这个很奇怪,HDFS是有租约恢复机制的,但为什么没有关成功有点遗憾,之前分析的HDFS租约机制有些细节不太记得了,有时间在review下。