hdfs mv命令如何工作

How does hdfs mv command work

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

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

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

当用户调用hdfs dfs -mv时,HDFS保证重命名操作的原子性。当此命令为运行时,客户端对NameNode 进行RPC 调用。此 RPC 的 NameNode 实现在修改 inode 树时持有锁,并且仅在重命名完成后释放该锁,无论成功或失败。 (它可能会因权限或配额违规等原因而失败。)

由于实现完全在 NameNode 内执行并且仅操作文件系统元数据,因此不涉及实际的数据移动。在 hdfs dfs -mv 命令期间实际上没有与 DataNodes 交互。文件的所有块都保持不变,与索引节点关联的块列表也保持不变。 NameNode 只是简单地从一个地方获取该文件的 inode 并将其移动到文件系统树中的另一个地方。不可能破坏块数据。

由于 NameNode 提供了重命名的保证原子实现,因此也不存在元数据损坏的可能性。不可能以 "half-completed" 状态结束,文件在两个地方都存在,或者更糟的是,被完全删除。

现在我需要在上面的答案上添加一个细微的变化。大多数时候,当 运行ning HDFS shell 命令时,通常将 HDFS 作为后备文件系统进行交互。然而,这并不是唯一可能的文件系统实现。 Apache Hadoop 发行版附带 S3, Azure Storage and 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

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

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

您可以轻松测试它。我会举例说明。

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

    我运行以下命令:

    hdfs fsck /tmp/1.txt -files -blocks -locations 
    

    我得到以下输出:

    /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]]
    
  2. 我将 (mv) 文件 /tmp/1.txt 移动到 /tmp/1_renamed.txt,它位于同一目录 /tmp.

    我运行以下命令:

    hdfs fsck /tmp/1_renamed.txt -files -blocks -locations 
    

    我得到以下输出:

    /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]]
    
  3. 我将 (mv) 文件 /tmp/1_renamed.txt 移动到 /tmp1/1.txt,它在不同的目录下 /tmp1.

    我运行以下命令:

    hdfs fsck /tmp1/1.txt -files -blocks -locations 
    

    我得到以下输出:

    /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]]
    

可以看到,3次mv操作后的block report是一样的:

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]]

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

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

  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
    

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

  2. distcp命令

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