DistCp

目录

前言

常用命令

选项

更新和覆盖

不同HDFS版本间的复制

MapReduce和副效应


前言

DistCp即distributed copy,分布式复制的意思,是集群间用于处理高I/O复制的工具。其底层基于MapReduce,因此具有分布式的能力,容错性以及对异常的监控和上报能力。它将文件和目录列表展开到映射任务的输入中,每个任务将复制源列表中指定文件的一个分区。

本文的目的是描述新的DistCp的设计、它的新特性、它们的最佳使用以及与遗留实现的任何偏差。

常用命令

DistCp最常见的用法就是集群内文件的复制:

hadoop distcp hdfs://nn1:8020/foo/bar hdfs://nn2:8020/bar/foo

还可以在命令行中指定多个源目录:

hadoop distcp hdfs://nn1:8020/foo/a hdfs://nn1:8020/foo/b hdfs://nn2:8020/bar/foo

或者使用-f选项,从文件里获得多个源,使用-f选项:

hadoop distcp -f hdfs://nn1:8020/srclist hdfs://nn2:8020/bar/foo

其中srclist 的内容是
    hdfs://nn1:8020/foo/a
    hdfs://nn1:8020/foo/b

当从多个源复制文件时,如果两个源冲突,DistCp会停止复制并打印出错信息, 如果在目的路径发生冲突,会根据选项设置解决。 默认情况会跳过已经存在的目标文件。

每次操作结束时都会报告跳过的文件数目,但是如果某些操作在当前操作中失败,但之后的尝试却成功了, 那么报告的信息可能不够准确。每个TaskTracker必须能够与源端和目的端文件系统进行访问和交互。对于HDFS来说,源和目的端要运行相同版本的协议或者使用向下兼容的协议。复制完成后,建议生成源端和目的端文件的列表,并交叉检查,来确认复制是成功的。 因为DistCp使用MapReduce和文件系统API进行操作,所以这三者或它们之间有任何问题,都会影响到复制操作。

一些Distcp命令可能会执行失败,但当带上-update参数再次进行执行时,将被成功执行。但用户在如此操作之前应该对该命令的语法很熟悉。值得注意的是,当另一个客户端同时在向源文件写入时,复制操作很有可能会失败。 尝试覆盖HDFS上正在被写入的文件的操作也会失败。 如果一个源文件在复制之前被移动或删除了,复制失败同时输出异常 FileNotFoundException。

选项

选项索引

标识描述备注
-p[rbugp]Preserve
  r: replication number
  b: block size
  u: user
  g: group
  p: permission
修改次数不会被保留。并且当指定 -update 时,更新的状态不会被同步,除非文件大小不同(比如文件被重新创建)。
-i忽略失败这个选项会比默认情况提供关于复制的更精确的统计, 同时它还将保留失败复制操作的日志,这些日志信息可以用于调试。最后,如果一个map失败了,但并没完成所有分块任务的尝试,这不会导致整个作业的失败。
-log <logdir>记录日志到 <logdir>DistCp为每个文件的每次尝试复制操作都记录日志,并把日志作为map的输出。 如果一个map失败了,当重新执行时这个日志不会被保留。
-m <num_maps>同时复制的最大数目指定了复制数据时map的数目。请注意并不是map数越多吞吐量越大。
-overwrite覆盖目标如果一个map失败并且没有使用-i选项,不仅仅那些复制失败的文件,这个分块任务中的所有文件都会被重新复制。它会改变生成目标路径的语义,用户要小心使用这个选项。
-update如果源和目标的大小不一样则进行覆盖像之前提到的,这不是"同步"操作。 执行覆盖的唯一标准是源文件和目标文件大小是否相同;如果不同,则源文件替换目标文件。 它也改变生成目标路径的语义, 用户要小心使用这个选项。
-f <urilist_uri>使用<urilist_uri> 作为源文件列表这等价于把所有文件名列在命令行中。 urilist_uri 列表应该是完整合法的URI。

更新和覆盖

这里给出一些 -update和 -overwrite的例子。 考虑一个从/foo/a 和 /foo/b 到 /bar/foo的复制,源路径包括:

    hdfs://nn1:8020/foo/a
    hdfs://nn1:8020/foo/a/aa
    hdfs://nn1:8020/foo/a/ab
    hdfs://nn1:8020/foo/b
    hdfs://nn1:8020/foo/b/ba
    hdfs://nn1:8020/foo/b/ab

如果没设置-update或 -overwrite选项, 那么两个源都会映射到目标端的 /bar/foo/ab。 如果设置了这两个选项,每个源目录的内容都会和目标目录的内容做比较。DistCp碰到这类冲突的情况会终止操作并退出。默认情况下,/bar/foo/a 和 /bar/foo/b 目录都会被创建,所以并不会有冲突。

现在考虑一个使用-update合法的操作:

distcp -update hdfs://nn1:8020/foo/a hdfs://nn1:8020/foo/b hdfs://nn2:8020/bar

其中源路径/大小:

    hdfs://nn1:8020/foo/a
    hdfs://nn1:8020/foo/a/aa 32
    hdfs://nn1:8020/foo/a/ab 32
    hdfs://nn1:8020/foo/b
    hdfs://nn1:8020/foo/b/ba 64
    hdfs://nn1:8020/foo/b/bb 32

和目的路径/大小:

    hdfs://nn2:8020/bar
    hdfs://nn2:8020/bar/aa 32
    hdfs://nn2:8020/bar/ba 32
    hdfs://nn2:8020/bar/bb 64

会产生:

    hdfs://nn2:8020/bar
    hdfs://nn2:8020/bar/aa 32
    hdfs://nn2:8020/bar/ab 32
    hdfs://nn2:8020/bar/ba 64
    hdfs://nn2:8020/bar/bb 32

只有nn2的aa文件没有被覆盖。如果指定了 -overwrite选项,所有文件都会被覆盖。

DistCp会尝试着均分需要复制的内容,这样每个map复制差不多相等大小的内容。 但因为文件是最小的复制粒度,所以配置增加同时复制(如map)的数目不一定会增加实际同时复制的数目以及总吞吐量。

如果没使用-m选项,DistCp会尝试在调度工作时指定map的数目 为 min (total_bytes / bytes.per.map, 20 * num_task_trackers), 其中bytes.per.map默认是256MB。

建议对于长时间运行或定期运行的作业,根据源和目标集群大小、复制数量大小以及带宽调整map的数目。

不同HDFS版本间的复制

对于不同Hadoop版本间的复制,用户应该使用HftpFileSystem。 这是一个只读文件系统,所以DistCp必须运行在目标端集群上(更确切的说是在能够写入目标集群的TaskTracker上)。 源的格式是 hftp://<dfs.http.address>/<path> (默认情况dfs.http.address是 <namenode>:50070)。

MapReduce和副效应

像前面提到的,map复制输入文件失败时,会带来一些副效应。

  • 除非使用了-i,任务产生的日志会被新的尝试替换掉。
  • 除非使用了-overwrite,文件被之前的map成功复制后当又一次执行复制时会被标记为 "被忽略"。
  • 如果map失败了mapred.map.max.attempts次,剩下的map任务会被终止(除非使用了-i)。
  • 如果mapred.speculative.execution被设置为 final和true,则复制的结果是未定义的。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值