DistCp(分布式拷贝)是用于大规模集群内部和集群之间拷贝的工具。 它使用Map/Reduce实现文件分发,错误处理和恢复,以及报告生成。 它把文件和目录的列表作为map任务的输入,每个任务会完成源列表中部分文件的拷贝。
DistCp使用Map/Reduce和文件系统API进行操作。
对于HDFS来说,源和目的端要运行相同版本的协议或者使用向下兼容的协议。
拷贝完成后,建议生成源端和目的端文件的列表,并交叉检查,来确认拷贝真正成功。
DistCp最常用在集群之间的文件或目录的拷贝, 如下命令:
hadoop distcp hdfs://nn1:8020/foo/bar hdfs://nn2:8020/bar/foo
该命令会把nn1集群的/foo/bar目录下的所有文件或目录名展开并存储到一个临时文件中,这些文件内容的拷贝工作被分配给多个map任务, 然后每个TaskTracker分别执行从nn1到nn2的拷贝操作。
注意:DistCp使用绝对路径进行操作。
命令说明
usage: distcp OPTIONS [source_path...] <target_path>
OPTIONS
-append | 重用目标文件中的现有数据,并在可能的情况下向其添加新数据 |
-async | 应该阻止distcp执行 |
-atomic | 提交所有更改或不提交 |
-bandwidth <arg> | 以MB为单位指定每个映射的带宽,接受带宽的一部分。 |
-blocksperchunk <arg> | 如果设置为正值,则具有大于此值的块的文件将被拆分为<blocksperchunk>块的块,以并行传输,然后在目标位置重新组合。默认情况下,<blocksperchunk>为0,文件将完整传输而不拆分。仅当源文件系统实现getBlockLocations方法并且目标文件系统实现concat方法时,此开关才适用 |
-copybuffersize <arg> | 要使用的复制缓冲区的大小。默认情况下,<copybuffersize>为8192B。 |
-delete | 从目标中删除,源中缺少文件。删除仅适用于更新或覆盖选项 |
-diff <arg> | 使用快照差异报告来识别源和目标之间的差异 |
-direct | 将文件直接写入目标位置,避免临时文件重命名。 |
-f <arg> | 需要复制的文件列表 |
-filelimit <arg> | (不建议使用!)限制复制到<= n的文件数 |
-filters <arg> | 文件路径,该文件包含要从副本中排除的路径的字符串列表。 |
-i | 忽略复制期间的失败 |
-log <arg> | DFS上保存distcp执行日志的文件夹 |
-m <arg> | 用于复制的最大并发映射数 |
-numListstatusThreads <arg> | 用于构建文件列表的线程数(最多40个)。 |
-overwrite | 选择无条件覆盖目标文件(即使它们存在)。 |
-p <arg> | 保留状态(rbugpcaxt)(复制,块大小,用户,组,权限,校验和类型,ACL,XATTR,时间戳)。如果-p没有指定<arg>,则保留复制,块大小,用户,组,权限,校验和类型和时间戳。当源路径和目标路径都位于/.reserved/raw层次结构中时(仅HDFS),将保留raw。* xattrs。 raw。* xattrpreservation与-p标志无关。有关更多详细信息,请参考DistCp文档。 |
-rdiff <arg> | 使用目标快照差异报告来确定对目标所做的更改 |
-sizelimit <arg> | (不建议使用!)限制复制到<= n个字节的文件数 |
-skipcrccheck | 是否在源路径和目标路径之间跳过CRC检查。 |
-strategy <arg> | 要使用的复制策略。默认是根据文件大小划分工作 |
-tmp <arg> | 用于原子提交的中间工作路径 |
-update | 更新目标,仅复制丢失的文件或目录 |
-v | 在“跳过/复制”日志中记录其他信息(路径,大小) |
-xtrack <arg> | 将有关丢失的源文件的信息保存到指定目录 |
注: source_path和target_path需要带上地址前缀以区分不同的集群。
选项说明
1、带宽限流: -bandwidth <arg>
2、增量数据同步: -update、-append、-diff
update 只拷贝不存在的文件或者目录,解决了新增文件、目录的同步;
append 追加写目标下已经存在的文件,解决已存在文件的增量更新同步;
diff 通过快照的diff对比信息来同步源端路径与目标路径,解决删除或重命名类型文件的同步。
3、复制的最大并发映射数: -m <arg>
如果没使用-m选项,DistCp会尝试在调度工作时指定map的数目 为 min (total_bytes / bytes.per.map, 20 * num_task_trackers), 其中bytes.per.map默认是256MB。
实例:
1、单个源目录同步:
hadoop distcp hdfs://nn1:8020/foo hdfs://nn2:8020/bar
2、同步nn1新增的文件和目录(nn2中不存在的文件和目录):
hadoop distcp -update hdfs://nn1:8020/foo/p hdfs://nn2:8020/bar
3、追加nn2下以存在的文件
hadoop distcp -append hdfs://nn1:8020/foo/a hdfs://nn2:8020/bar/a
4、多个源目录同步:
hadoop distcp hdfs://nn1:8020/foo/a \
hdfs://nn1:8020/foo/b \
hdfs://nn2:8020/bar/foo
或者使用-f选项,从文件里获得多个源:
hadoop distcp -f hdfs://nn1:8020/srclist \
hdfs://nn2:8020/bar/foo
其中srclist 的内容是
hdfs://nn1:8020/foo/a
hdfs://nn1:8020/foo/b
不同HDFS版本间的拷贝
对于不同Hadoop版本间的拷贝,用户应该使用HftpFileSystem。 这是一个只读文件系统,所以DistCp必须运行在目标端集群上(更确切的说是在能够写入目标集群的TaskTracker上)。 源的格式是 hftp://<dfs.http.address>/<path> (默认情况dfs.http.address是 <namenode>:50070)。
Map/Reduce和副效应
像前面提到的,map拷贝输入文件失败时,会带来一些副效应。
- 除非使用了-i,任务产生的日志会被新的尝试替换掉。
- 除非使用了-overwrite,文件被之前的map成功拷贝后当又一次执行拷贝时会被标记为 "被忽略"。
- 如果map失败了mapred.map.max.attempts次,剩下的map任务会被终止(除非使用了-i)。
- 如果mapred.speculative.execution被设置为 final和true,则拷贝的结果是未定义的。
参考至:http://hadoop.apache.org/docs/r1.0.4/cn/distcp.html