文章目录

  • 1. 参数详解
  • 1. `-p`
  • 2. `-m `
  • 3. `-update和-overwrite`
  • 其他参数
  • DistCpOptions类
  • 2.使用javaApi
  • 3. distcp map


1. 参数详解

distcp2和3的参数有所变动。以下参数为2版本参数。
1. 不加任何参数复制:
不会保留文件时间,不会同步文件owner。

$ hadoop distcp  \ hdfs://cluster-host1:9000/user/whb \
hdfs://10.179.25.59:9000/test/01

distcp java distcp java api_distcp


distcp java distcp java api_hdfs_02


单独复制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 <dir

指定log输出

(测试暂未生效)

-m <num

最大map数量

-f <urilist_uri

指定源列表文件

这等价于把所有文件名列在命令行中。 urilist_uri 列表应该是完整合法的URI。

(测试暂未生效)

-update

如果源和目标的大小不一样(字节大小)则进行覆盖

执行覆盖的唯一标准是源文件和目标文件大小是否相同;如果不同,则源文件替换目标文件。

-overwrite

如果一个map失败并且没有使用-i选项,不仅仅那些拷贝失败的文件,这个分块任务中的所有文件都会被重新拷贝。

有目标文件,也直接覆盖掉

1. -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
2. -m <num>

最大map个数。如最大4个map

hadoop distcp  -m 4 \
hdfs://cluster-host1:9000/user/whb/ww \
hdfs://10.179.25.59:9000/test/10
3. -update和-overwrite
  • -update用于从源复制目标上不存在或具有不同内容的文件。
  • -overwrite覆盖目标文件,即使它们存在于源文件中或具有相同的内容。

相当于overwriteupdate的加强版。
另外注意:
当使用了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 <arg> 以MB为单位指定每个map的带宽,注意由于在互联网数据传输都是以二进制形式传输,因此,我们将MB的文件需要转换称大Mb需要乘以八个比特位,因此1Gb = 1024MB = 1024MB * 8bits = 8192Mb

-delete 从目标中删除,源文件丢失

-skipcrccheck 是否跳过源和源之间的CRC检查目标路径。

-strategy <arg> 复制策略使用。默认是分工基于文件大小

DistCpOptions类

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);
  }

2.使用javaApi

...
		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) {
    ...}

3. distcp map

对于如下5个文件的distcp:

[hadoop@hadoop bin]$ ./hadoop distcp  /user/whb /ec/whb1212-1

distcp java distcp java api_List_03


由于有1个目录,6个文件。因此在map端有6个map

distcp java distcp java api_distcp java_04


点进去,发现:

distcp java distcp java api_hdfs_05


distcp java distcp java api_distcp_06


建新的目录,需要一个map,其他的每个map,复制一个文件。

如果加上-update,再次复制,即目录存在时,就只有5个map了,不需要再起map来建目录。

[hadoop@hadoop bin]$ ./hadoop distcp  -update /user/whb /ec/whb1212-1

distcp java distcp java api_hadoop_07