使用distcp命令
操作场景
distcp是一种在集群间或集群内部拷贝大量数据的工具。它利用MapReduce任务实现大量数据的分布式拷贝。
前提条件
- 已安装Yarn客户端或者包括Yarn的客户端。例如安装目录为“/opt/client”。
- 各组件业务用户由MRS集群管理员根据业务需要创建。安全模式下,“机机”用户需要下载keytab文件。“人机”用户第一次登录时需修改密码。(普通模式不涉及)
- 如需在集群间拷贝数据,拷贝数据的集群双方都需要启用集群间拷贝数据功能。
操作步骤
- 登录安装客户端的节点。
- 执行以下命令,切换到客户端安装目录。
cd /opt/client
- 执行以下命令配置环境变量。
source bigdata_env
- 如果集群为安全模式,执行distcp命令的用户所属的用户组必须为supergroup组,且执行以下命令进行用户认证。普通模式集群无需执行用户认证。
kinit 组件业务用户
- 直接执行distcp命令。例如:
hadoop distcp hdfs://hacluster/source hdfs://hacluster/target
distcp常见用法
- 最常见的distcp用法,示例如下:
hadoop distcp -numListstatusThreads 40 -update -delete -prbugpaxtq hdfs://cluster1/source hdfs://cluster2/target
在上述命令中:
- -numListstatusThreads指定了40个构建被拷贝文件的列表的线程数;
- -update -delete表示将源位置和目标位置的文件同步,删除掉目标位置多余的文件,注意如果需要增量拷贝文件,请将-delete删掉;
- -prbugpaxtq与-update配合,表示被拷贝文件的状态信息也会被更新;
- hdfs://cluster1/source、hdfs://cluster2/target分别表示源位置和目标位置。
- 集群间的数据拷贝,示例如下:
hadoop distcp hdfs://cluster1/foo/bar hdfs://cluster2/bar/foo
集群cluster1和集群cluster2之间的网络必须保持互通,且两个集群需要使用相同或兼容的HDFS版本。
- 多个源目录的数据拷贝,示例如下:
hadoop distcp hdfs://cluster1/foo/a \ hdfs://cluster1/foo/b \ hdfs://cluster2/bar/foo
上面的命令的效果是将集群cluster1的文件夹a、b拷贝到集群cluster2的“/bar/foo”目录下,它的效果等效于下面的命令:
hadoop distcp -f hdfs://cluster1/srclist \ hdfs://cluster2/bar/foo
其中srclist里面的内容如下。注意运行distcp命令前,需要将srclist文件上传到HDFS上。
hdfs://cluster1/foo/a hdfs://cluster1/foo/b
- update和overwrite选项的用法,-update用于被拷贝的文件在目标位置中不存在,或者更新目标位置中被拷贝文件的内容;-overwrite用于覆盖在目标位置中已经存在的文件。
假设,源位置的文件结构如下:
hdfs://cluster1/source/first/1 hdfs://cluster1/source/first/2 hdfs://cluster1/source/second/10 hdfs://cluster1/source/second/20
不加选项的命令:
hadoop distcp hdfs://cluster1/source/first hdfs://cluster1/source/second hdfs://cluster2/target
上述命令默认会在目标位置创建文件夹first、second,所以拷贝结果如下:
hdfs://cluster2/target/first/1 hdfs://cluster2/target/first/2 hdfs://cluster2/target/second/10 hdfs://cluster2/target/second/20
加两个选项中任一个选项的命令,例如加update选项:
hadoop distcp -update hdfs://cluster1/source/first hdfs://cluster1/source/second hdfs://cluster2/target
上述命令只会将源位置的内容拷贝到目标位置,所以拷贝结果如下:
hdfs://cluster2/target/1 hdfs://cluster2/target/2 hdfs://cluster2/target/10 hdfs://cluster2/target/20
- 如果多个源位置有相同名称的文件,则distcp命令会失败。
- 在不使用update和overwrite选项的情况下,如果被拷贝文件在目标位置中已经存在,则该文件会跳过。
- 在使用update选项的情况下,如果被拷贝文件在目标位置中已经存在,但文件内容不同,则目标位置的文件内容会被更新。
- 在使用overwrite选项的情况下,如果被拷贝文件在目标位置中已经存在,目标位置的文件依然会被覆盖。
- 其它命令选项:
表1 其他命令选项 选项
描述
-p[rbugpcaxtq]
当同时使用-update选项时,即使被拷贝文件的内容没有被更新,它的状态信息也会被更新
r:副本数,b:块大小,u:所属用户,g:所属用户组,p:许可,c:校验和类型,a:访问控制,t:时间戳,q:Quota信息
-i
拷贝过程中忽略失败
-log <logdir>
指定日志路径
-v
指定日志中的额外信息
-m <num_maps>
最大的同时运行的执行拷贝的任务数
-numListstatusThreads
构建被拷贝文件的文件列表时所用的线程数,该选项会提高distcp的运行速度
-overwrite
覆盖目标位置的文件
-update
如果源位置和目标位置的文件的大小,校验和不同,则更新目标位置的文件
-append
当同时使用-update选项时,追加源位置的文件内容到目标位置的文件
-f <urilist_uri>
将<urilist_uri>文件的内容作为需要拷贝的文件列表
-filters
指定一个本地文件,其文件内容是多条正则表达式。当被拷贝的文件与某条正则表达式匹配时,则该文件不会被拷贝
-async
异步运行distcp命令
-atomic {-tmp <tmp_dir>}
指定一次原子性的拷贝,可以添加一个临时目录的选项,作为拷贝过程中的暂存目录
-bandwidth
指定每个拷贝任务的传输带宽,单位MB/s
-delete
删除掉目标位置中存在,但源位置不存在的文件。该选项通常会和-update配合使用,表示将源位置和目标位置的文件同步,删除掉目标位置多余的文件
-diff <oldSnapshot> <newSnapshot>
将新旧版本之间的差异内容,拷贝到目标位置的旧版本文件中
-skipcrccheck
是否跳过源文件和目标文件之间的CRC校验
-strategy {dynamic|uniformsize}
指定拷贝任务的拷贝策略,默认策略是uniformsize,即每个拷贝任务复制相同的字节数
加密区数据拷贝
默认情况下,执行distcp时会比较文件系统提供的校验和,以验证数据是否已成功复制到目标。从普通目录到加密区、加密区到普通目录、加密区中不同目录之间复制时,由于数据块内容不同,文件系统校验和将不匹配。
在这种情况下,可以指定“-skipcrccheck”和“-update”标志以避免验证校验和。当使用“-skipcrccheck”时,distcp在每个文件的复制完成后立即执行文件大小比较来检查文件的完整性。
例如,执行命令如下:
hadoop distcp -skipcrccheck -update /encryptedpath /commonpath
使用Distcp进行跨集群拷贝如果一个集群配置了KMS透明加密,需要确保另个集群也配置了KMS透明加密,否则未配置透明加密集群使用distcp到配置透明加密集群将会失败。
拷贝原始加密区数据
为了保留HDFS加密区数据,HDFS引入了一个新的虚拟路径前缀“/.reserved/raw/”,该前缀路径允许集群管理员直接访问文件系统中的基础数据块,允许集群管理员在不需要访问加密密钥的情况下拷贝数据,并避免了解密和重新加密数据的操作。这种情况源数据和复制之后的数据会完全相同,如果复制之后的数据使用新的EDEK重新加密将可能导致异常。
例如,执行命令如下:
hadoop distcp -px /.reserved/raw/encrptedpath /.reserved/raw/backpath
- 由于加密属性(如EDEK)保存在扩展属性“-px”中,为了可以解密文件,在distcp中使用“/.reserved/raw/”目录拷贝加密数据时,需要保留带有“-px”标志的扩展属性。
- 当前版本不支持该方式跨集群拷贝。
- 如需使用上述命令执行拷贝操作请确保两个目录使用相同的EZK加密。
distcp常见使用问题
- 当使用distcp命令时,如果某些被拷贝的文件内容较大时,建议修改执行拷贝任务的mapreduce的超时时间。可以通过在distcp命令中指定mapreduce.task.timeout选项实现。例如,修改超时时间为30分钟,则命令如下:
hadoop distcp -Dmapreduce.task.timeout=1800000 hdfs://cluster1/source hdfs://cluster2/target
您也可以使用选项filters,不对这种大文件进行拷贝,命令示例如下:
hadoop distcp -filters /opt/client/filterfile hdfs://cluster1/source hdfs://cluster2/target
其中filterfile是本地文件,它的内容是多条用于匹配不拷贝文件路径的正则表达式,它的内容示例如下:
.*excludeFile1.* .*excludeFile2.*
- 当使用distcp命令时,命令异常退出,报“java.lang.OutOfMemoryError”的错误。
这个问题的原因是拷贝任务运行时所需的内存超过了客户端设置的内存上限(默认为128MB)。可以通过修改“<客户端安装路径>/HDFS/component_env”中的“CLIENT_GC_OPTS”来修改客户端的内存上限。例如,需要设置该内存上限为1GB,则设置:
CLIENT_GC_OPTS="-Xmx1G"
在修改完后,使用如下命令刷新客户端配置,使之生效:
source <客户端安装路径>/bigdata_env
- 使用dynamic策略执行distcp命令时,命令异常退出,报“Too many chunks created with splitRatio”的错误。
这个问题的原因是“distcp.dynamic.max.chunks.tolerable”的值(默认值为20000)小于“distcp.dynamic.split.ratio”的值(默认为2)乘以Map数。即一般出现在Map数超过10000的情况。可以通过-m参数降低Map数小于10000:
hadoop distcp -strategy dynamic -m 9500 hdfs://cluster1/source hdfs://cluster2/target
或通过-D参数指定更大的“distcp.dynamic.max.chunks.tolerable”的值:
hadoop distcp -Ddistcp.dynamic.max.chunks.tolerable=30000 -strategy dynamic hdfs://cluster1/source hdfs://cluster2/target