hdfs Cannot obtain block length for LocatedBlock异常的解决

问题的发现

在备份hdfs的数据到本地磁盘时,使用了get命令,结果报错了,具体的错误就是Cannot obtain block length for LocatedBlock这个异常。发现这个问题之后就开始解决问题。

问题出现的原因

写hdfs的上游是flume,所以就去查出错数据当天是否调整过flume服务。通过flume的日志发现当天有写hdfs时候,datanode没有响应的错误日志,正在写的日志文件就没有正常的关闭。

这里就出现了hdfs的租约未被释放的问题,租约就是在HDFS中,当每次客户端用户往某个文件中写入数据的时候,为了保持数据的一致性,此时其它客户端程序是不允许向此文件同时写入数据的,租约的信息是存在namenode中的,也就是说当hdfs系统被关闭时,flume还在继续写该文件,同时也会报错,文件还是处于打开状态。

所以我们要解决这个问题就需要释放租约。

恢复租约的方式

首先先查看有哪些文件是租约没有释放的
hadoop fsck /hafs/path -openforwrite
然后执行
hdfs debug recoverLease -path
释放租约

如果未被释放租约的文件太多的话,可以执行批量释放操作
hadoop fsck /hafs/path -openforwrite | egrep -v '^\.+$' | egrep "MISSING|OPENFORWRITE" | grep -o "/[^ ]*" | sed -e "s/:$//" | xargs -i hdfs debug recoverLease -path {}

总结

该问题的出现主要是下游关闭时上游还在写,导致租约没有释放掉。在以后的升级或者重启hdfs时,需要提前先把flume或者其他上游写hdfs操作停止后,在执行hdfs系统的操作,才可以避免该问题的出现。