hdfs mv命令如何工作

Man*_*akh 5 filesystems hadoop hdfs

我想知道mvhdfs 中的命令是如何工作的?

  1. 它只是一个没有任何实际数据移动的象征性变化吗?

    • 如果moveTo目录存在(可能在diff分区上)
    • 如果moveTo是一个新目录
  2. 在hadoop中移动大文件时是否可能损坏数据?那么,cpdistcp更安全的选择?

Chr*_*oth 12

当用户调用时hdfs dfs -mv,HDFS保证重命名操作的原子性.运行此命令时,客户端对NameNode进行RPC调用.此RPC的NameNode实现在修改inode树时保持锁定,并且只有在重命名完成后才会成功锁定或成功锁定.(由于许可或配额违规等原因,它可能会失败.)

由于实现完全在NameNode内执行并且仅操纵文件系统元数据,因此不涉及实际的数据移动.事实上,在hdfs dfs -mv命令期间没有与DataNode的交互.所有文件的块保持不变,与inode关联的阻止列表保持不变.NameNode只是从一个位置获取该文件的inode,并将其移动到文件系统树中的另一个位置.不会破坏块数据.

由于NameNode提供了重命名的保证原子实现,因此也不存在元数据损坏的可能性.不可能最终处于"半完成"状态,文件存在于两个地方,甚至更糟,完全被删除.

现在我需要在上面的答案中添加一个微妙的变化.大多数情况下,在运行HDFS shell命令时,通常与HDFS作为后备文件系统进行交互.但是,这不是唯一可能的文件系统实现.Apache Hadoop发行版附带了用于S3,Azure存储OpenStack Swift的备用文件系统插件.还有许多供应商已经创建了自己的文件系统插件.这些备用文件系统是否提供原子重命名语义是这些其他文件系统的实现细节.S3和Swift插件实现重命名为copy-then-delete,因此它们绝对不提供原子性保证.Azure存储插件通过使用Azure存储blob租约确实为原子重命名提供了一些可选支持,但它不是默认行为.

此外,由于这个原因,不可能hdfs dfs -mv跨越不同的文件系统.您必须使用复制命令,然后它将涉及完整的数据副本.当您尝试跨文件系统重命名时会发生以下情况.该示例尝试hdfs dfs -mv在我的HDFS安装中运行源文件,并在本地文件系统上运行目标.该命令被拒绝.

> hdfs dfs -mv hdfs:///testData file:///tmp/testData
mv: `hdfs:///testData': Does not match target filesystem
Run Code Online (Sandbox Code Playgroud)

问题的最后一部分询问复制时是否可能损坏数据.Hadoop将在读取文件时执行校验和验证,因此预计客户端不会看到损坏的数据. DistCp还可以执行源和目标之间的校验和比较作为后处理步骤.


Man*_*lur 5

mv(移动)只是一个元数据操作。没有像cp(复制)那样的数据移动。

您可以轻松测试它。我将用例子来解释。

  1. 我有一个文件/tmp/1.txt

    我运行以下命令:

    hdfs fsck /tmp/1.txt -files -blocks -locations 
    
    Run Code Online (Sandbox Code Playgroud)

    我得到以下输出:

    /tmp/1.txt 5 bytes, 1 block(s):  OK
    0. BP-1788638071-172.23.206.41-1439815305280:blk_1073747956_7133 len=5 repl=1 [DatanodeInfoWithStorage[192.168.56.1:50010,DS-cf19d920-d98b-4877-9ca7-c919df1a869a,DISK]]
    
    Run Code Online (Sandbox Code Playgroud)
  2. 我将 ( mv) 文件移动/tmp/1.txt/tmp/1_renamed.txt同一目录下/tmp

    我运行以下命令:

    hdfs fsck /tmp/1_renamed.txt -files -blocks -locations 
    
    Run Code Online (Sandbox Code Playgroud)

    我得到以下输出:

    /tmp/1_renamed.txt 5 bytes, 1 block(s):  OK
    0. BP-1788638071-172.23.206.41-1439815305280:blk_1073747956_7133 len=5 repl=1 [DatanodeInfoWithStorage[192.168.56.1:50010,DS-cf19d920-d98b-4877-9ca7-c919df1a869a,DISK]]
    
    Run Code Online (Sandbox Code Playgroud)
  3. 我将 ( mv) 文件移动/tmp/1_renamed.txt/tmp1/1.txt另一个目录下/tmp1

    我运行以下命令:

    hdfs fsck /tmp1/1.txt -files -blocks -locations 
    
    Run Code Online (Sandbox Code Playgroud)

    我得到以下输出:

    /tmp1/1.txt 5 bytes, 1 block(s):  OK
    0. BP-1788638071-172.23.206.41-1439815305280:blk_1073747956_7133 len=5 repl=1 [DatanodeInfoWithStorage[192.168.56.1:50010,DS-cf19d920-d98b-4877-9ca7-c919df1a869a,DISK]]
    
    Run Code Online (Sandbox Code Playgroud)

可以看到,3次mv操作后的块报告是相同的:

0. BP-1788638071-172.23.206.41-1439815305280:blk_1073747956_7133 len=5 repl=1 [DatanodeInfoWithStorage[192.168.56.1:50010,DS-cf19d920-d98b-4877-9ca7-c919df1a869a,DISK]]
Run Code Online (Sandbox Code Playgroud)

确认了这一点,mv只需重命名Name Node中的文件名即可。在“Chris Nauroth”给出的另一个答案中,他已经清楚地解释了mv操作是如何执行的。

数据损坏:cp使用或 复制时数据可能会损坏distcp。但是,在这两种情况下,您都可以检查腐败情况。

  1. cp命令

    hadoop fs -checksum可用于检查文件的校验和。

    我将文件复制/tmp/1GB/part-m-00000到另一个目录/tmp1/part-m-00000。然后我执行了以下命令:

    hadoop fs -checksum /tmp/1GB/part-m-00000 /tmp1/part-m-00000
    
    /tmp/1GB/part-m-00000   MD5-of-262144MD5-of-512CRC32    0000020000000000000400008f15c32887229c0495a23547e2f0a29a
    /tmp1/part-m-00000      MD5-of-262144MD5-of-512CRC32    0000020000000000000400008f15c32887229c0495a23547e2f0a29a
    
    Run Code Online (Sandbox Code Playgroud)

    您可以看到原始文件和复制文件的校验和匹配。因此,复制文件后,您可以执行hadoop fs -checksum命令来检查两个文件的校验和是否匹配。

  2. distcp命令

    默认情况下,distcp复制操作完成后比较源文件和目标文件的校验和。如果校验和不匹配,则distcp将该复制操作标记为FAILED。您可以通过使用选项调用来禁用校验distcp和比较-skipcrccheck