hdfs mv命令如何工作

时间:2015-12-29 13:59:06

标签: hadoop filesystems hdfs

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

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

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

2 个答案:

答案 0 :(得分:9)

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

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

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

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

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

> hdfs dfs -mv hdfs:///testData file:///tmp/testData
mv: `hdfs:///testData': Does not match target filesystem

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

答案 1 :(得分:1)

mv(move)只是一个元数据操作。 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]]
    

    我得到以下输出:

    mv
  3. 我将{/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]]
    

    我得到以下输出:

    mv
  4. 您可以看到,所有3 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

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

    数据损坏: 使用distcpcp进行复制时,数据可能会损坏。但是,在这两种情况下,您都可以检查是否存在腐败。

    1. 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

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

    2. distcp命令

      默认情况下,distcp会在完成复制操作后比较源文件和目标文件的校验和。如果校验和不匹配,则FAILED会将复制操作标记为distcp。您可以通过-skipcrccheck选项调用SELECT TOP 100000 SUM ([dbo].[Entry].[Amount]) AS 'Total Charges' 来停用校验和比较。