Hadoop 复制的两个方法

546次阅读
没有评论

直奔主题,目前在Hadoop 集群上我常用的执行Copy的命令就是 cp,前两天复制一批数据,如果可以直接搬走使用mv那是最快啦!使用cp的时候觉得好慢,搜索一下“如何加速Hadoop 复制”,然后出现了本文。

distcp

distcp 是一个Hadoop下实现并行复制的命令。

distcp的典型应用就是在两个HDFS集群中拷贝文件,如果两个集群使用的Hadoop版本相同,可以使用hdfs标识符: hadoop distcp hdfs://namenode1/foo hdfs://namenode2/bar 这条命令会把第一个集群(namenode为命令中指定的namenode1)中的/foo目录拷贝到第二个集群中的/bar目录下,于是在第二个集群中就得到了/bar/foo这样的目录结构,我们也可以指定多个拷贝源,但拷贝目的地只有一个。要注意的是,指定拷贝路径的时候要使用绝对路径。

distcp命令是以mapreduce作业的形式实现的,只不过此作业没有reduce任务。每一个文件是由一个map任务来拷贝的,distcp尽量把大小之和相同的各个文件导入到同一个map任务中。这样可以每个map任务拷贝的数据量大致相同。 Map任务的个数是按如下方式决定的: 1)考虑到创建每个map任务的开销,每个map任务至少应处理256MB大小的数据(如果总输入文件的大小小于256MB,则把这些输入数据全部交给一个map任务执行)。例如,一个1GB大小的输入数据会被分配四个map任务来拷贝。 2)如果待拷贝的数据实在很大,这时候就不能只按每个map任务256MB输入数据的标准来划分了,因为这样可能需要创建很多map任务。这是可以按每个datanode20个map任务来划分,例如如果有1000GB的输入数据和100个节点,这是就会启动100*20=2000个map任务来拷贝数据,每个map任务拷贝512MB数据。同时我们也可通过-m选项指定要使用的map数,例如-m 1000就会只启动1000个map任务,每个map任务拷贝1GB数据。

默认情况下,如果在拷贝的目的地同名文件已经存在,则会默认跳过这些文件。可以通过-overwrite选项指定覆盖掉同名文件,或者通过-update选项来更新同名文件。

选项索引

标识 描述 备注
-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选项,所有文件都会被覆盖。

Map/Reduce和副效应

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

  • 除非使用了-i,任务产生的日志会被新的尝试替换掉。
  • 除非使用了-overwrite,文件被之前的map成功拷贝后当又一次执行拷贝时会被标记为 “被忽略”。
  • 如果map失败了mapred.map.max.attempts次,剩下的map任务会被终止(除非使用了-i)。
  • 如果mapred.speculative.execution被设置为 finaltrue,则拷贝的结果是未定义的。

参考:

https://hadoop.apache.org/docs/r1.0.4/cn/distcp.html

admin
版权声明:本站原创文章,由admin2020-12-18发表,共计2920字。
转载提示:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)