一、事发背景
上个月的某一天,由于集群空间不足,公司有一位权限较高的员工通过跳板机在某个线上集群执行手动清理命令,疯狂地执行hadoop fs -rmr -skipTrash /user/hive/warehouse/xxxxx
,突然,不知道是编辑器的问题还是换行问题,命令被截断,命令变成了hadoop fs -rmr -skipTrash /user/hive/warehouse
,悲剧此刻开始发生!?
/user/hive/warehouse
目录下存储了所有hive表的数据,关联公司多个业务线,一旦丢失,意味着巨大的损失。由于加了-skipTrash
参数,意味着删除的数据不会放入回收站而是直接删除,这个参数不加的话很容易挽回,回收站里直接找,可惜逃不了墨菲定律,最担心的事还是发生了。
领导解决不了的事,只有小弟上,看我接下来怎样四两拨千斤。
二、应急措施
运维第一时间找到我,当时说误删了 /user/hive/warehouse
目录。当时我也是一震惊,完了完了!凭我仅有的直觉,立马停掉了HDFS集群!后面证明是很明智的选择。
直观的方案
- 通过快照恢复?hdfs快照从来没用过,也没创建过快照,所以此路不通
- 通过回收站恢复?删除时加了-skipTrash参数,不会放回收站,此路也不通
- 删库跑路成为一代传奇人物?嗯,还不错
三、分析过程
想要恢复数据,首先要理解hdfs删除文件的过程,各个文件系统的删除逻辑都不一样,理解了hdfs的删除过程,才知道上面那一条hadoop fs -rmr xxxx
究竟干了什么,究竟还有没有救,怎么去救等等问题。
-
hdfs文件删除过程
下面是hdfs删除路径的方法,源码路径
org.apache.hadoop.hdfs.server.namenode.FSNamesystem.delete()
boolean delete(String src, boolean recursive, boolean logRetryCache) throws IOException { waitForLoadingFSImage(); BlocksMapUpdateInfo toRemovedBlocks = null; writeLock(); boolean ret = false; try { checkOperation(OperationCategory.WRITE); checkNameNodeSafeMode("Cannot delete " + src); toRemovedBlocks = FSDirDeleteOp.delete( // @1 this, src, recursive, logRetryCache); ret = toRemovedBlocks != null; } catch (AccessControlException e) { logAuditEvent(false, "delete", src); throw e; } finally { writeUnlock(); } getEditLog().logSync(); if (toRemovedBlocks != null) { removeBlocks(toRemovedBlocks); // @2 } logAuditEvent(true, "delete", src); return ret; }
代码@1里面做了三件比较重要的事
①从NameNode维护的的目录树里面删除路径,这也是为什么执行删除操作之后就无法再通过
hadoop fs -ls xxx
或其它api方式再查看到路径的根本原因②找出被删路径关联的block信息,每个文件包含多个block块,分布在各个DataNode,此时并未真正物理删除DataNode上物理磁盘上的block块
③记录删除日志到editlog(这一步也很重要,甚至是后面恢复数据的关键)
代码@