distcp2和3的参数有所变动。以下参数为2版本参数。
1. 不加任何参数复制:
不会保留文件时间,不会同步文件owner。
$ hadoop distcp \ hdfs://cluster-host1:9000/user/whb \
hdfs://10.179.25.59:9000/test/01
单独复制2副本的wordfile.txt到另一个集群时,默认变成3副本。
-rw-r--r-- 3 hadoop supergroup 51 2019-10-24 19:45 /test/01/wordfile.txt
指定多个源:
hadoop distcp \
hdfs://cluster-host1:9000/user/whb/ww/hi.txt \
hdfs://cluster-host1:9000/user/whb/bb/bb.har/_masterindex \
hdfs://10.179.25.59:9000/test/11
结果:
[hadoop@hadoop1 ~]$ hadoop fs -ls /test/11
Found 2 items
-rw-r--r-- 3 hadoop supergroup 23 2019-10-24 21:37 /test/11/_masterindex
-rw-r--r-- 3 hadoop supergroup 12 2019-10-24 21:38 /test/11/hi.txt
标识 | 描述 | 备注 |
---|---|---|
-p[rbugp] | Preserve r: replication number b: block size u: user g: group p: permission |
表示保留哪些。修改次数不会被保留。 并且当指定 -update 时,更新的状态不会被同步,除非文件大小不同(比如文件被重新创建) |
-i | 忽略失败 | 一般不用(测试暂未生效) |
-log 指定log输出 |
(测试暂未生效) |
|
-m 最大map数量 |
| |
-f 指定源列表文件 |
这等价于把所有文件名列在命令行中。 urilist_uri 列表应该是完整合法的URI。 |
(测试暂未生效) |
-update | 如果源和目标的大小不一样(字节大小)则进行覆盖 | 执行覆盖的唯一标准是源文件和目标文件大小是否相同;如果不同,则源文件替换目标文件。 |
-overwrite | 如果一个map失败并且没有使用-i选项,不仅仅那些拷贝失败的文件,这个分块任务中的所有文件都会被重新拷贝。 有目标文件,也直接覆盖掉 |
-p
加上-p参数(不用加后边的子参数),
hadoop distcp -p \
hdfs://cluster-host1:9000/user/whb \
hdfs://10.179.25.59:9000/test/03
会将副本数、owner、时间同步过去。
[hadoop@hadoop1 ~]$ hadoop fs -ls /test/03
Found 6 items
drwxr-xr-x - whb didi 0 2019-08-26 20:50 /test/03/bb
drwxr-xr-x - whb didi 0 2019-08-27 16:07 /test/03/hi-out
-rw-r--r-- 3 whb didi 51 2019-08-27 14:26 /test/03/hi.txt
drwxr-xr-x - whb didi 0 2019-08-06 20:56 /test/03/output
-rw-r--r-- 2 whb didi 51 2019-06-28 12:15 /test/03/wordfile.txt
drwxr-xr-x - whb didi 0 2019-08-26 20:41 /test/03/ww
-m
最大map个数。如最大4个map
hadoop distcp -m 4 \
hdfs://cluster-host1:9000/user/whb/ww \
hdfs://10.179.25.59:9000/test/10
-update和-overwrite
相当于overwrite
是update
的加强版。
另外注意:
当使用了update或overwrite参数时,关于官网说的只复制下边的文件,并未复现。
https://hadoop.apache.org/docs/stable/hadoop-distcp/DistCp.html
这里-p、-m、-overwrite
都是常用参数,大多数情况下我们期望拷贝后数据权限保持一致,通过-p
参数来完成权限一致性,拷贝并行度则由-m
参数来调节。至于-overwrite
往往和-delete合用,用来起到dst和src的一个diff功能。至于-update是很不靠谱的参数
,因为只有当源和目标文件的大小不一致时distcp才会覆盖拷贝,如果大小一致,虽然内容不同distcp也依然会跳过这个文件不做拷贝。
-append
重新使用目标文件中的现有数据并追加新的如果可能,和update
一起使用
Append is valid only with update options(暂未生效)
-bandwidth
以MB为单位指定每个map的带宽,注意由于在互联网数据传输都是以二进制形式传输,因此,我们将MB的文件需要转换称大Mb需要乘以八个比特位,因此1Gb = 1024MB = 1024MB * 8bits = 8192Mb
-delete
从目标中删除,源文件丢失
-skipcrccheck
是否跳过源和源之间的CRC检查目标路径。
-strategy
复制策略使用。默认是分工基于文件大小
distcp2.7.2版本的所有参数如下。
public class DistCpOptions {
private boolean atomicCommit = false;
private boolean syncFolder = false; // 默认值,不同步(不同步的是什么?)
private boolean deleteMissing = false;
private boolean ignoreFailures = false; // 不能忽略map错误
private boolean overwrite = false; // 默认不会覆盖
private boolean append = false;
private boolean skipCRC = false; // 默认需要校验文件checksum
private boolean blocking = true;
private boolean useDiff = false;
private int maxMaps = DistCpConstants.DEFAULT_MAPS; // 默认 20
private int mapBandwidth = DistCpConstants.DEFAULT_BANDWIDTH_MB; // 默认100
private String sslConfigurationFile;
private String copyStrategy = DistCpConstants.UNIFORMSIZE; // 默认 uniformsize
private EnumSet<FileAttribute> preserveStatus = EnumSet.noneOf(FileAttribute.class); //保留选项,默认为空
private boolean preserveRawXattrs;
private Path atomicWorkPath;
private Path logPath;
private Path sourceFileListing;
private List<Path> sourcePaths;
private String fromSnapshot;
private String toSnapshot;
private Path targetPath;
// targetPathExist is a derived field, it's initialized in the
// beginning of distcp.
private boolean targetPathExists = true;
public static enum FileAttribute{
REPLICATION, BLOCKSIZE, USER, GROUP, PERMISSION, CHECKSUMTYPE, ACL, XATTR, TIMES;
public static FileAttribute getAttribute(char symbol) {
for (FileAttribute attribute : values()) {
if (attribute.name().charAt(0) == Character.toUpperCase(symbol)) {
return attribute;
}
}
throw new NoSuchElementException("No attribute for " + symbol);
}
}
...
上述枚举类 FileAttribute
是保留选项的参数。
其中,构造器有三种形式:
public DistCpOptions(List<Path> sourcePaths, Path targetPath) {...}
public DistCpOptions(Path sourceFileListing, Path targetPath) {...}
public DistCpOptions(DistCpOptions that) {
if (this != that && that != null) {
this.atomicCommit = that.atomicCommit;
this.syncFolder = that.syncFolder;
this.deleteMissing = that.deleteMissing;
this.ignoreFailures = that.ignoreFailures;
this.overwrite = that.overwrite;
this.skipCRC = that.skipCRC;
this.blocking = that.blocking;
this.maxMaps = that.maxMaps;
this.mapBandwidth = that.mapBandwidth;
this.sslConfigurationFile = that.getSslConfigurationFile();
this.copyStrategy = that.copyStrategy;
this.preserveStatus = that.preserveStatus;
this.preserveRawXattrs = that.preserveRawXattrs;
this.atomicWorkPath = that.getAtomicWorkPath();
this.logPath = that.getLogPath();
this.sourceFileListing = that.getSourceFileListing();
this.sourcePaths = that.getSourcePaths();
this.targetPath = that.getTargetPath();
this.targetPathExists = that.getTargetPathExists();
}
}
关于-p参数,直接使用preserve
即可添加参数。
public void preserve(FileAttribute fileAttribute) {
for (FileAttribute attribute : preserveStatus) {
if (attribute.equals(fileAttribute)) {
return;
}
}
preserveStatus.add(fileAttribute);
}
...
List<Path> sourceList = new ArrayList<Path>();
sourceList.add(srcPath);
DistCpOptions options = new DistCpOptions(sourceList, new Path(task.getCopyDstPath()));
options.setSyncFolder(false); //不需要同步
options.setDeleteMissing(false);
options.setSkipCRC(false); //同副本复制需要校验filechecksums
options.setIgnoreFailures(false);//不能忽略map错误
options.setOverwrite(true); //核心数据需要覆盖目标目录已经存在的文件
options.setMaxMaps(100);
options.setMapBandwidth(10);
options.preserve(DistCpOptions.FileAttribute.USER);
options.preserve(DistCpOptions.FileAttribute.GROUP);
options.preserve(DistCpOptions.FileAttribute.TIMES);
options.preserve(DistCpOptions.FileAttribute.PERMISSION);
options.preserve(DistCpOptions.FileAttribute.REPLICATION);
options.preserve(DistCpOptions.FileAttribute.BLOCKSIZE); //必须确保块大小相同,否则会导致filechecksum不一致
options.preserve(DistCpOptions.FileAttribute.CHECKSUMTYPE);
options.setBlocking(true);
DistCp4EC distCp = new DistCp4EC(conf, options);
Job job = distCp.execute();
} catch (Exception e) {
...}
对于如下5个文件的distcp:
[hadoop@hadoop bin]$ ./hadoop distcp /user/whb /ec/whb1212-1
由于有1个目录,6个文件。因此在map端有6个map
点进去,发现:
建新的目录,需要一个map,其他的每个map,复制一个文件。
如果加上-update,再次复制,即目录存在时,就只有5个map了,不需要再起map来建目录。
[hadoop@hadoop bin]$ ./hadoop distcp -update /user/whb /ec/whb1212-1