官方文档
概述
DistCp(分布式拷贝)是用于大规模集群内部和集群之间拷贝的工具。 它使用Map/Reduce实现文件分发,错误处理和恢复,以及报告生成。 它把文件和目录的列表作为map任务的输入,每个任务会完成源列表中部分文件的拷贝。 由于使用了Map/Reduce方法,这个工具在语义和执行上都会有特殊的地方。
基本使用方法
DistCp最常用在集群之间的拷贝:
bash$ hadoop distcp hdfs://nn1:8020/foo/bar \
hdfs://nn2:8020/bar/foo
这条命令会把nn1集群的/foo/bar目录下的所有文件或目录名展开并存储到一个临时文件中,这些文件内容的拷贝工作被分配给多个map任务, 然后每个TaskTracker分别执行从nn1到nn2的拷贝操作。注意DistCp使用绝对路径进行操作。
命令行中可以指定多个源目录:
bash$ hadoop distcp hdfs://nn1:8020/foo/a \
hdfs://nn1:8020/foo/b \
hdfs://nn2:8020/bar/foo
或者使用-f选项,从文件里获得多个源:
bash$ hadoop distcp -f hdfs://nn1:8020/srclist \
hdfs://nn2:8020/bar/foo
其中srclist 的内容是
hdfs://nn1:8020/foo/a
hdfs://nn1:8020/foo/b
当从多个源拷贝时,如果两个源冲突,DistCp会停止拷贝并提示出错信息, 如果在目的位置发生冲突,会根据选项设置解决。 默认情况会跳过已经存在的目标文件(比如不用源文件做替换操作)。每次操作结束时,都会报告跳过的文件数目,但是如果某些拷贝操作失败了,但在之后的尝试成功了, 那么报告的信息可能不够精确。
- 拷贝完成后,建议生成源端和目的端文件的列表,并交叉检查,来确认拷贝真正成功。
- 因为DistCp使用Map/Reduce和文件系统API进行操作,所以这三者或它们之间有任何问题都会影响拷贝操作。
- 一些Distcp命令的成功执行可以通过再次执行带-update参数的该命令来完成, 但用户在如此操作之前应该对该命令的语法很熟悉。
- 当另一个客户端同时在向源文件写入时,拷贝很有可能会失败。 尝试覆盖HDFS上正在被写入的文件的操作也会失败。 如果一个源文件在拷贝之前被移动或删除了,拷贝失败同时输出异常 FileNotFoundException。
更新和覆盖问题
这里给出一些 -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命令是支持带宽限速的,迁移数据我们走的是专线,但是distcp会将带宽流量吃满,导致其他的业务在高峰期使用这条专线的时候存在丢包的情况。
版本
- DistCp是Apache Hadoop自带的工具,目前存在两个版本,distcp1和distcp2
- fastcopy是Facebook Hadoop中自带的,相比于Distcp,它能明显加快同节点数据拷贝速度,尤其是Hadoop 2.0稳定版发布后,当需要在不同NameNode间(HDFS Federation)迁移数据时,FastCopy将发挥它的最大用武之地。
DistCp1
DistCp1使用了MapReduce并发拷贝数据,它将整个数据拷贝过程转化为一个map-only Job以加快拷贝速度。由于需要保证文件中block块的有序性,mapreduce以文件为分发单位。也就是说,一个文件不能被切分成不同部分让多个任务并行拷贝,最小只能做到一个文件交给一个任务。加上map阶段是静态分配map task的,分发时容易造成负载不均匀。
DistCp2
DistCp2针对DistCp1在易用性和性能等方面的不足,提出了一系列改进点,包括通过去掉不必要的检查缩短了目录扫描时间、动态分配各个Map Task的数据量、可对拷贝限速避免占用过多网络流量、支持HSFTP等。
DistCp2采用动态分配map task机制,”多劳多得“。DistCp2通过动态分配Map Task数据量解决了该问题,它实现了一个DynamicInputFormat,该InputFormat将待拷贝的目录文件分解成很多的chunk,其中每个chunk的信息(位置,文件名等)写到一个以“.chunk.K”(K是一个数字)结尾的HDFS文件中,目录文件被分成多个chunk.K文件,执行快的map task可以多领取几个chunk.K文件,运行快的Map Task能够多领取一些“任务”,而运行慢得则领取少一些,进而提高数据拷贝速度。解决了负载不均衡的问题,但仍存在传输效率低下的问题。但相比于DistCp1,则要高效得多,尤其是在文件数据庞大,且大小差距较大的情况下。
不管是DistCp1还是DistCp2,在数据拷贝过程中均存在数据低效问题,尤其在Hadoop 2.0时代表现突出。Hadoop 2.0引入了HDFS Federation,当我们进行Hadoop(1.0升级到2.0)升级或者将一个NameNode扩展到多个NameNode时,需将集群中的单个NameNode上的部分数据迁移到其他NameNode上,此时就需要用到DistCp这样的工具。在HDFS Federation设计中,一个HDFS集群中可以有多个NameNode,但DataNode是共享的,因此,在数据迁移过程中,大部分数据所在的节点不会变(在同一个DataNode上),只需将其指向新的NameNode(即数据位置不变,元数据转移到其他NameNode上)。如果使用DistCp,则需要将数据重新通过网络拷贝一份,然后将旧的删除,性能十分低下。考虑到数据仍在同一个节点上,则采用文件硬链接(Linux中的ln命令)就可以了, Facebook的FastCopy正是采用了这一方案。FastCopy已经被集成到了Facebook Hadoop中的DistCp中,有兴趣的读者可以试用一下。