昨天公司集群升级,采集平台的flume agent没有停,导致一些文件异常,无法读,也无法使用cp或者get命令,报Cannot obtain block length for LocatedBlock

首先使用fsck来检查下该文件,命令hdfs fsck file_path -files -blocks -locations,提示如下:

1
2
Status: HEALTHY
Total size: 0 B (Total open files size: 18935B)

现实文件依然是打开的,使用命令hadoop fsck file_path -openforwrite查看目录下打开的文件,显示:

1
2
3
4
5
17/08/03 15:21:50 WARN ssl.FileBasedKeyStoresFactory: The property 'ssl.client.truststore.location' has not been set, no TrustStore will be loaded
Connecting to namenode via http://namenode:50070
FSCK started by portal (auth:KERBEROS_SSL) from /10.160.xx.22 for path file_path at Thu Aug 03 15:21:51 CST 2017
............/file_path/xx.1501646609139.lzo.tmp 827 bytes, 1 block(s), OPENFORWRITE: ......................./file_path/xx.1501650099752.lzo 333 bytes, 1 block(s), OPENFORWRITE:
/file_path/xx.1501650099752.lzo: MISSING 1 blocks of total size 333 B........................Status: CORRUPT

显示OPENFORWRITE,也有MISSING信息,推断应该是文件没有close成功。

之所以没有关成功,通过看flume的log发现集群是safemode状态,无法close成功,flume catch住异常之后只是抛出了个WARN,设置failedToClose为true,然后继续执行代码进行rename操作,rename操作没有成功被放到一个线程中不断的去尝试rename,等集群恢复之后,rename成功了。

下面就是怎么恢复文件,文件是打开状态是因为namenode依然记录这该文件的租约,该租约没有被关闭,使用appendToFile命令检验下

1
2
3
4
5
6
// 这个命令执行之后,允许在窗体中输入字符串,Ctrl + C退出stdin,此后stdin数据将会追加到hdfs文件中。
$ hadoop dfs -appendToFile - /file_path/341.lzo
DEPRECATED: Use of this script to execute hdfs command is deprecated.
Instead use the hdfs command for it.

appendToFile: Failed to APPEND_FILE /file_path/341.lzo for DFSClient_NONMAPREDUCE_-1675067591_1 on 10.120.233.47 because this file lease is currently owned by DFSClient_NONMAPREDUCE_-1514310687_13 on 10.200.128.130

租约冲突了,确认租约没有关闭。

在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下。