HBase ExportSnapshot报FileNotFoundException问题分析
最近有客户反馈说在迁移HBase数据的过程中经常碰到FileNotFoundException的异常,导致整个迁移任务失败。
该迁移方案主要是使用ExportSnapshot将指定表的数据从A集群迁移到B集群,从问题现象上看,异常主要发生在大表的迁移上,小表没有发生过异常。任务的异常信息如图:
从该异常信息来看,很容易联想到是A集群的HFile文件不存在了。那么导致文件不存在的原因是啥?被HFile Cleaner清理了还是被人为删除了?
从HFile Cleaner的清理逻辑来分析,应该不存在这种可能,因为Cleaner在判断一个文件能否被清理时,会检查该文件是否有被snapshot依赖,存在依赖的文件是不会清理的。
那会不会是人为删除?从客户的反馈来说,没有做个类似的删除操作,从NameNode的审计日志也没有找到该文件被删除的记录。
通过HDFS的命令去A集群查看该报错的文件,发现该文件实际上是存在的并且是在表目录下,而不是报错的/hbase/archvie目录下,但是ExportSnapshot在拷贝文件时,源集群的/hbase/data/和/hbase/archive都会查找,只有拷贝到目标集群才是优先写到/hbase/archive目录,那会不会写目标集群出现了问题?
再回过头来查看报错的信息,有一个很重要的点被忽略了,如下图标记内容,该异常是在addBlock的时候抛出的,那就意味着该异常是发生在写文件而不是读文件,所以该FileNotFoundException应该是发生在B集群,也就是数据迁移的目标集群,而不是源集群。
查找目标集群的NameNode审计日志,可以发现报错的文件的确是被删除了,通过删除的节点ip和用户来判断,应该就是HMaster删除的。
从目前的分析结果来看,我们又回到了一开始的怀疑点,这个文件是被目标集群的HFile Cleaner删除了。不是说好快照依赖的文件不会被删除吗?
这里得先介绍一下ExportSnapshot的代码逻辑,ExportSnapshot的实现逻辑简单点说就是把源集群的快照文件和所依赖的HFile文件拷贝到目标集群,这样用户就可以在目标集群查看到该快照并且进行快照恢复操作。
理论上,先把快照文件拷贝到目标集群后,然后再拷贝HFile文件,因为快照文件的存在,HFile Cleaner就不会清理拷贝过来的HFile文件。但是问题的关键就出现在拷贝快照文件这一步,ExportSnapshot默认是把快照文件拷贝到目标集群的/hbase/.hbase-snapshot/.tmp目录下,然后等MR任务把所有的HFile文件拷贝完成后再将/hbase/.hbase-snapshot/.tmp目录下的快照移到/hbase/.hbase-snapshot目录下,所以在整个拷贝HFile的过程中,这个放在.tmp目录下的快照是无法被HFile Cleaner识别的。如果一个文件的拷贝时间超过了HFile Cleaner的清理文件的存活时间(默认5分钟),该文件就可能会被删除,这样就会导致该文件在写一个新的block时,抛出FileNotFoundException的异常。
如何解决该问题?只需要在ExportSnapshot命令后面加上参数-Dsnapshot.export.skip.tmp=true即可解决该问题,具体的命令格式如:
hbase org.apache.hadoop.hbase.snapshot.ExportSnapshot -Dsnapshot.export.skip.tmp=true -snapshot …
加上该参数后,快照文件将会跳过.tmp目录,直接拷贝到/hbase/.hbase-snapshot目录。需要注意,修改后如果ExportSnapshot 任务中途执行失败或被手动中止,会导致目标集群的快照文件残留,再次执行任务会报错。需要手动清楚残留的快照目录或者在ExportSnapshot命令添加参数-overwrite解决。
- 点赞
- 收藏
- 关注作者
评论(0)