问题的发现
在备份 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 系统的操作,才可以避免该问题的出现。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于