本文会主要解释在client端,rm命令会做一些什么行为。
首先,当我们在命令行中输入rm命令时,HDFS会将-rm作为参数传递给FsShell,FsShell会做一个command register的行为,说白了就是将java类与命令对应起来,这里大家如果好奇可以搜索“FsShell” 去探究细节,我们这里不做赘述。
通过FsShell,我们会来到org.apache.hadoop.fs.shell.Delete,在Delete类下,一共定义了四个子类
Rm -- 对应我们日常使用的“-rm", 负责一切与HDFS相关的删除操作
Rmr -- 与“-rm -r” 完全相同
Rmdir -- 主要用于清理空文件夹
Expunge -- 创建checkpoint并清理trash目录
我们最常用到的Rm类下,除去一些对删除参数的判断与过滤,client端会先尝试moveToTrash操作,如果moveToTrash失败,才会直接给NN发送delete请求:
我们trace moveToTrash方法可以来到TrashPolicyDefault.moveToTrash(Path):
在这里,客户端会生成本次删除的trash目录并判断文件/文件夹是否已经在trash目录下:
尝试创建trash目录并在trash目录已存在的情况下将trash+timestamp设为新的trash目录:
下面还有一个类似操作就不都贴出来了。之后就是会向server端发送rename到trash目录的请求了。
这里关于创建trash目录与rename操作,会做两次尝试,为了防止在第一次尝试时,创建trash目录结束后,正好做了createCheckPoint的行为,导致trash目录不存在,最终删除失败。
当然如果出现了两次尝试都出现这种情况的时候呢,这边建议直接汇报领导,看看是公司里哪个大聪明干的。