2021SC@SDUSC
本次我将对tools中的DisCp Guide进行分析
DistCp
概念
DistCp(分布式拷贝)是一种用于大型集群间/集群内拷贝的工具。它使用MapReduce来实现其分发、错误处理和恢复以及报告。它将文件和目录列表展开为映射任务的输入,每个任务将复制源列表中指定文件的一个分区。
使用
DistCp最常见的调用是集群间复制:
bash$ hadoop distcp hdfs://nn1:8020/foo/bar \
hdfs://nn2:8020/bar/foo
这将扩展下的命名空间/foo/bar在nn1上,将它的内容划分到一组映射任务中,并在每个节点管理器上从nn1到nn2。 还可以在命令行上指定多个源目录
bash$ hadoop distcp hdfs://nn1:8020/foo/a \
hdfs://nn1:8020/foo/b \
hdfs://nn2:8020/bar/foo
bash$ hadoop distcp -f hdfs://nn1:8020/srclist \
hdfs://nn2:8020/bar/foo
当从多个源复制时,如果两个源发生冲突,DistCp将中止复制,并显示一条错误消息,但目标上的冲突将通过选择指定的。默认情况下,目标上已经存在的文件将被跳过(即不会被源文件替换)。每个作业结束时都会报告跳过文件的计数,但如果复印机对其文件的某个子集失败,但在以后的尝试中成功,则该计数可能不准确。
重要的是,每个节点管理器都可以到达源文件系统和目标文件系统并与之通信。对于HDFS,源和目标必须运行相同版本的协议或使用向后兼容的协议;请参见[在版本之间复制](#在HDFS的版本之间复制)。
复制后,建议生成并交叉检查源和目标的列表,以验证复制是否真正成功。由于DistCp同时采用了映射/缩减和文件系统应用编程接口,这三者中的任何一个或两者之间的问题都可能会对拷贝产生负面和无声的影响。有些人已经成功了-更新允许执行第二遍,但是用户在尝试之前应该熟悉它的语义。
需要注意的是:如果另一个客户端仍在写入源文件,复制很可能会失败。尝试覆盖正在目标位置写入的文件在HDFS也应该会失败。如果源文件在复制前被(重新)移动,复制将失败,并显示文件未找到异常。
同步
差异选项使用快照差异将文件从源群集同步到目标群集。它复制、重命名和删除快照差异列表中的文件。
用法:
hadoop distcp -update -diff <from_snapshot> <to_snapshot> <source> <destination>
例如:
hadoop distcp -update -diff snap1 snap2 /src/ /dst/
上面的命令应用snapshot中的更改snap1到snap2(即快照不同于snap1到snap2)在/src/到/dst/。显然,这需要/src/要同时拥有这两个快照snap1和snap2。但是目的地/dst/还必须有一个与同名的snapshot从<from_snapshot>,在这种情况下快照1。目的地/dst/不应有新的文件操作(创建、重命名、删除),因为snap1。请注意,当此命令完成时,新的快照snap2不会创建于/dst/。
例如接下来的一个实验:
实验1:同步两个相邻快照的差异
开始前的一些准备。
# Create source and destination directories
hdfs dfs -mkdir /src/ /dst/
# Allow snapshot on source
hdfs dfsadmin -allowSnapshot /src/
# Create a snapshot (empty one)
hdfs dfs -createSnapshot /src/ snap1
# Allow snapshot on destination
hdfs dfsadmin -allowSnapshot /dst/
# Create a from_snapshot with the same name
hdfs dfs -createSnapshot /dst/ snap1
# Put one text file under /src/
echo "This is the 1st text file." > 1.txt
hdfs dfs -put 1.txt /src/
# Create the second snapshot
hdfs dfs -createSnapshot /src/ snap2
# Put another text file under /src/
echo "This is the 2nd text file." > 2.txt
hdfs dfs -put 2.txt /src/
# Create the third snapshot
hdfs dfs -createSnapshot /src/ snap3
然后我们运行distcp同步:
hadoop distcp -update -diff snap1 snap2 /src/ /dst/
如果我们再次运行相同的命令,我们将得到DistCp同步失败异常,因为目标添加了新文件1.txt因为快照1。也就是说,如果我们移除1.txt手动从/dst/并运行同步,命令将会成功。
实验2:同步两个不相邻快照的差异
首先从实验1开始做一个清理。
hdfs dfs -rm -skipTrash /dst/1.txt
运行同步命令,注意 <to_snapshot>已从更改为 snap2在Experiment 1到 snap3。
hadoop distcp -update -diff snap1 snap3 /src/ /dst/
实验3:同步文件删除操作
从实验2的结尾继续:
hdfs dfs -rm -skipTrash /dst/2.txt
# Create snap2 at destination, it contains 1.txt
hdfs dfs -createSnapshot /dst/ snap2
# Delete 1.txt from source
hdfs dfs -rm -skipTrash /src/1.txt
# Create snap4 at source, it only contains 2.txt
hdfs dfs -createSnapshot /src/ snap4
立即运行同步命令:
hadoop distcp -update -diff snap2 snap4 /src/ /dst/
尽管两者都有/src/和/dst/具有同名的snap2,snapshots不需要具有相同的内容。这意味着,如果你有一个1.txt在/dst/s快照2但是它们有不同的内容,1.txt仍将从中移除/dst/。sync命令不会检查将要删除的文件的内容。它只是遵循以下快照差异列表<from_snapshot> 从<from_snapshot>
另外,如果我们删除1.txt从/dst/创建前快照2在/dst/在上面的步骤中,这样/dst/’s snap2没有1.txt在运行sync命令之前,该命令仍然会成功。它不会在尝试删除时抛出异常1.txt从/dst/这是不存在的。
原始命名空间扩展属性保留
如果目标和所有源路径名都在/.保留/原始层次结构,则“raw”命名空间扩展属性将被保留。raw ' xattrs由系统用于内部功能,如加密元数据。只有当用户通过/.保留/原始等级制度。
原始xattrs仅根据是否/来保存。提供保留/原始前缀。-p(保存,见下文)标志不影响原始xattrs的保存。
为了防止原始xattrs被保留,只需不要使用/.保留/原始任何源路径和目标路径的前缀。
如果/.保留/原始仅在源路径和目标路径的子集上指定前缀,将显示错误并返回非0退出代码。
DistCp的体系结构
新DistCp的组件可分为以下几类:
驱动程序
拷贝列表生成器
输入格式和地图缩减组件
驱动程序
DistCp驱动程序组件负责:
-
通过以下方式解析命令行上传递给DistCp命令的参数:
- 选项栏,以及
- DistCpOptionsSwitch
-
将命令参数组装到适当的DistCpOptions对象中,并初始化DistCp。这些论点包括:
- 源路径
- 目标位置
- 复制选项(例如,是否更新-复制、覆盖、保留哪些文件属性等。)
-
通过以下方式编排复制操作:
- 调用复制列表生成器来创建要复制的文件列表。
- 设置并启动Hadoop地图缩减作业来执行拷贝。
- 根据选项,要么立即将句柄返回给Hadoop MR作业,要么等待直到完成。
解析器元素只在命令行中执行(或者如果调用了DistCp::run())。DistCp类也可以通过编程方式使用,通过构造DistCpOptions对象,并适当地初始化DistCp对象。
拷贝列表生成器
复制列表生成器类负责创建要从源复制的文件/目录列表。它们检查源路径(文件/目录,包括通配符)的内容,并记录需要复制到序列文件中的所有路径,以供DistCp Hadoop作业使用。本模块中的主要课程包括:
- 复制列表:应该由任何复制列表生成器实现实现的接口。还提供了选择具体复制列表实现的工厂方法。
- SimpleCopyListing:实施复制列表它接受多个源路径(文件/目录),并递归列出每个路径下的所有单个文件和目录,以便复制。
- globbedpcopy listing:的另一个实现复制列表扩展源路径中的通配符。
- FileBasedCopyListing:实施复制列表从指定文件中读取源路径列表。
根据源文件列表是否在DistCpOptions中指定,源列表以下列方式之一生成:
- 如果没有源文件列表globbedpcopy listing被使用。所有的通配符都被展开,所有的展开都被转发到SimpleCopyListing,simplecopy listing反过来构造列表(通过每个路径的递归下降)。
- 如果指定了源文件列表,则FileBasedCopyListing被使用。源路径从指定的文件中读取,然后转发到globbedpcopy listing。然后按照上面的描述构建列表。
人们可以通过提供拷贝列表接口的定制实现来定制构建拷贝列表的方法。这里DistCp的行为与传统DistCp的不同之处在于如何考虑路径进行复制。
您还可以通过传递当前支持的CopyFilter接口实现来定制对不应复制的文件的过滤,或者编写新的实现。这可以通过设置distcp.filters.class在远程选项中:
- distcp.filters.class到“RegexCopyFilter”。如果您正在使用这个实现,您将不得不传递“复制过滤器”distcp.filters.file它包含用于过滤的正则表达式。支持java.util.regex.Pattern指定的正则表达式。
- distcp.filters.class到“RegexpInConfigurationFilter”。如果您正在使用这个实现,您将不得不使用distcp.exclude-file-regex参数。支持java.util.regex.Pattern指定的正则表达式。与“RegexCopyFilter”相比,这是一种更动态的方法。
- distcp.filters.class到“TrueCopyFilter”。如果没有指定上述选项,这将用作默认实现。
遗留实现只列出了那些肯定必须复制到目标上的路径。例如,如果目标上已经存在文件(并且-覆盖未指定),该文件甚至不在MapReduce复制作业中考虑。在安装过程中(即在地图缩减作业之前)确定这一点涉及文件大小和校验和比较,这可能很耗时。
新的DistCp将此类检查推迟到MapReduce作业,从而减少了设置时间。由于这些检查在多个映射中并行进行,因此性能得到了进一步提高。
输入格式和映射减少组件
输入格式和映射减少组件负责文件和目录从源路径到目标路径的实际拷贝。在拷贝列表生成期间创建的列表文件在执行拷贝时被消耗。这里感兴趣的类别包括:
-
UniformSizeInputFormat:org . Apache . Hadoop . MapReduce . input format的这种实现在平衡跨地图的负载方面提供了与Legacy DistCp的等价性。UniformSizeInputFormat的目的是使每个地图副本的字节数大致相同。顺便说一下,列表文件被分成多组路径,这样每个InputSplit中文件大小的总和几乎等于其他所有映射。拆分并不总是完美的,但是它微不足道的实现降低了建立时间。
-
DynamicInputFormat和DynamicRecordReader:DynamicInputFormat实现了org . Apache . Hadoop . MapReduce . Inputformat,并且对DistCp是新的。列表文件被分成几个“块文件”,块文件的确切数量是Hadoop作业中请求的映射数量的倍数。在作业启动之前,每个映射任务都被“分配”到一个块文件中(通过将块重命名为任务的id)。方法从每个块中读取路径DynamicRecordReader,并在复制映射器中进行处理。处理完块中的所有路径后,将删除当前块并获取新块。该过程继续,直到没有更多块可用。这种“动态”方法允许更快的地图任务比更慢的任务消耗更多的路径,从而加快DistCp作业的整体速度。
-
复制映射器:这个类实现了物理文件拷贝。根据输入选项(在作业配置中指定)检查输入路径,以确定文件是否需要复制。仅当以下至少一项为真时,才会复制文件:
- 目标中不存在同名文件。
- 目标中存在同名文件,但文件大小不同。
- 目标中存在同名文件,但具有不同的校验和,并且-skiprccheck没有提到。
- 目标中存在同名文件,但是-覆盖已指定。
- 目标中存在同名文件,但块大小不同(需要保留块大小。
-
复制提交者:这个类负责DistCp作业的提交阶段,包括:
- 目录权限的保留(如果在选项中指定)
- 清理临时文件、工作目录等。