前言
在HDFS中,我们经常会碰到跨集群数据拷贝的场景,例如某些任务数据结果计算生成,然后问你启动任务把结果数据导出到另外一个集群中以作后续的分析等这样的用途。Hadoop作为一套成熟完善的系统,也为我们提供了专门的拷贝工具,Distcp,全称Distributed copy,意为分布式的拷贝。说到Distcp工具本身,很多同学估计不会陌生,不过本文笔者来聊聊Distcp基于HDFS fastcopy原理下的性能提升改造。在某些特定拷贝场景下,distcp+fastcopy模式能大大缩短大数据量拷贝的时间开销。
HDFS的fastcopy
首先,第一个问题,何为HDFS的fastcopy?HDFS fastcopy指的是一种不实际拷贝物理数据的数据拷贝方式,我们可以理解为其为一种元数据的拷贝,物理数据不动的数据拷贝方式。HDFS fastcopy目前并不是HDFS社区已经合入的一个功能,但是有对应的基本功能的patch实现,相关JIRA为HDFS-2139:Fast copy for HDFS。
Fastcopy的拷贝过程区别于原始数据拷贝方式的最大区别在于物理数据是通过建立hardlink的方式来做,省去了实际数据拷贝的过程,以此大大缩短数据拷贝的时间,原理图如下所示:
因为fastcopy是依赖于本地数据来建hardlink的,因此它在使用上有以下的限制:
DataNode需要是Federation模式,需要是被source NN, target NN所share。
所以我们不能使用fastcopy来做完全独立的集群间的数据拷贝。但是如果我们处于HDFS Federation模式的话,我们就能很好的利用这个功能了。
对比同样为数据拷贝工具distcp来说,目前fastcopy的实现比较的简单,在实际使用的时候存在着一些不足:
- 不能分布式的大规模并行拷贝。
- 也不能支持增量式的数据同步拷贝。
所以一个绝妙的改进想法自然的衍生而来:能否让Distcp的单个文件拷贝步骤通过fastcopy来做,同时保留distcp原来的功能行为,例如diff,update等功能。文件的拷贝走fastcopy的方式将会大大缩短distcp job的执行时间。
于是,我们进行了distcp支持fastcopy的改造。
Distcp工具支持fastcopy的改造
这部分的改造其实没有想象中那么复杂,改造关键点在于以下两点:
- 1)fastcopy在命令使用上不能和diff, update,append等这些存在增量数据拷贝的场景一同使用,在参数传入检查时就应该做出判断。我们只允许fastcopy在初始式的拷贝。
- 2)只替换文件copy实际发生的逻辑为fastcopy的拷贝,其它逻辑分毫不动,基本不破坏distcp的原有执行逻辑。
OK,基于以上两点的改造原则,我们做了下面的主要改动。
改动类RetriableFileCopyCommand的copyToFile方法
private long copyToFile(Path targetPath, FileSystem targetFS,
FileStatus sourceFileStatus, long sourceOffset, Mapper.Context context,
EnumSet<FileAttribute> fileAttributes, final FileChecksum sourceChecksum)
throws IOException {
final OutputStream outStream;
if (action == FileAction.OVERWRITE) {