问题的发现
在备份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系统的操作,才可以避免该问题的出现。