DistCp(分佈式拷貝)

概述

DistCp(分佈式拷貝)是用於大規模集羣內部和集羣之間拷貝的工具。 它使用Map/Reduce實現文件分發,錯誤處理和恢復,以及報告生成。 它把文件和目錄的列表作爲map任務的輸入,每個任務會完成源列表中部分文件的拷貝。 由於使用了Map/Reduce方法,這個工具在語義和執行上都會有特殊的地方。 這篇文檔會爲常用DistCp操作提供指南並闡述它的工作模型。

 

【文檔來源於Hadoop官方文檔(中文版),該文檔並非最新文檔,最新文檔爲distcp2的英文文檔。】

使用方法

基本使用方法

DistCp最常用在集羣之間的拷貝:

bash$ hadoop distcp hdfs://nn1:8020/foo/bar \ 
                    hdfs://nn2:8020/bar/foo

這條命令會把nn1集羣的/foo/bar目錄下的所有文件或目錄名展開並存儲到一個臨時文件中,這些文件內容的拷貝工作被分配給多個map任務, 然後每個TaskTracker分別執行從nn1nn2的拷貝操作。注意DistCp使用絕對路徑進行操作。

命令行中可以指定多個源目錄:

bash$ hadoop distcp hdfs://nn1:8020/foo/a \ 
                    hdfs://nn1:8020/foo/b \ 
                    hdfs://nn2:8020/bar/foo

或者使用-f選項,從文件裏獲得多個源:
bash$ hadoop distcp -f hdfs://nn1:8020/srclist \ 
                       hdfs://nn2:8020/bar/foo 

其中srclist 的內容是
    hdfs://nn1:8020/foo/a 
    hdfs://nn1:8020/foo/b

當從多個源拷貝時,如果兩個源衝突,DistCp會停止拷貝並提示出錯信息, 如果在目的位置發生衝突,會根據選項設置解決。 默認情況會跳過已經存在的目標文件(比如不用源文件做替換操作)。每次操作結束時 都會報告跳過的文件數目,但是如果某些拷貝操作失敗了,但在之後的嘗試成功了, 那麼報告的信息可能不夠精確(請參考附錄)。

每個TaskTracker必須都能夠與源端和目的端文件系統進行訪問和交互。 對於HDFS來說,源和目的端要運行相同版本的協議或者使用向下兼容的協議。 (請參考不同版本間的拷貝 )。

拷貝完成後,建議生成源端和目的端文件的列表,並交叉檢查,來確認拷貝真正成功。 因爲DistCp使用Map/Reduce和文件系統API進行操作,所以這三者或它們之間有任何問題 都會影響拷貝操作。一些Distcp命令的成功執行可以通過再次執行帶-update參數的該命令來完成, 但用戶在如此操作之前應該對該命令的語法很熟悉。

值得注意的是,當另一個客戶端同時在向源文件寫入時,拷貝很有可能會失敗。 嘗試覆蓋HDFS上正在被寫入的文件的操作也會失敗。 如果一個源文件在拷貝之前被移動或刪除了,拷貝失敗同時輸出異常 FileNotFoundException

選項

 

標識

描述

備註

-p[rbugp]

Preserve
  r: replication number
  b: block size
  u: user
  g: group
  p: permission

修改次數不會被保留。並且當指定 -update 時,更新的狀態不會 被同步,除非文件大小不同(比如文件被重新創建)。

-i

忽略失敗

就像在 附錄中提到的,這個選項會比默認情況提供關於拷貝的更精確的統計, 同時它還將保留失敗拷貝操作的日誌,這些日誌信息可以用於調試。最後,如果一個map失敗了,但並沒完成所有分塊任務的嘗試,這不會導致整個作業的失敗。

-log <logdir>

記錄日誌到 <logdir>

DistCp爲每個文件的每次嘗試拷貝操作都記錄日誌,並把日誌作爲map的輸出。 如果一個map失敗了,當重新執行時這個日誌不會被保留。

-m <num_maps>

同時拷貝的最大數目

指定了拷貝數據時map的數目。請注意並不是map數越多吞吐量越大。

-overwrite

覆蓋目標

如果一個map失敗並且沒有使用-i選項,不僅僅那些拷貝失敗的文件,這個分塊任務中的所有文件都會被重新拷貝。 就像下面提到的,它會改變生成目標路徑的語義,所以 用戶要小心使用這個選項。

-update

如果源和目標的大小不一樣則進行覆蓋

像之前提到的,這不是"同步"操作。 執行覆蓋的唯一標準是源文件和目標文件大小是否相同;如果不同,則源文件替換目標文件。 像 下面提到的,它也改變生成目標路徑的語義, 用戶使用要小心。

-f <urilist_uri>

使用<urilist_uri> 作爲源文件列表

這等價於把所有文件名列在命令行中。 urilist_uri 列表應該是完整合法的URI。


https://hadoop.apache.org/docs/r1.2.1/distcp2.html

 

更新和覆蓋

這裏給出一些 -update和 -overwrite的例子。 考慮一個從/foo/a  /foo/b  /bar/foo的拷貝,源路徑包括:

    hdfs://nn1:8020/foo/a 
    hdfs://nn1:8020/foo/a/aa 
    hdfs://nn1:8020/foo/a/ab 
    hdfs://nn1:8020/foo/b 
    hdfs://nn1:8020/foo/b/ba 
    hdfs://nn1:8020/foo/b/ab

如果沒設置-update或 -overwrite選項, 那麼兩個源都會映射到目標端的 /bar/foo/ab。 如果設置了這兩個選項,每個源目錄的內容都會和目標目錄的 內容 做比較。DistCp碰到這類衝突的情況會終止操作並退出。

默認情況下,/bar/foo/a  /bar/foo/b 目錄都會被創建,所以並不會有衝突。

現在考慮一個使用-update合法的操作:
distcp -update hdfs://nn1:8020/foo/a \ 
               hdfs://nn1:8020/foo/b \ 
               hdfs://nn2:8020/bar

其中源路徑/大小:

    hdfs://nn1:8020/foo/a 
    hdfs://nn1:8020/foo/a/aa 32 
    hdfs://nn1:8020/foo/a/ab 32 
    hdfs://nn1:8020/foo/b 
    hdfs://nn1:8020/foo/b/ba 64 
    hdfs://nn1:8020/foo/b/bb 32

和目的路徑/大小:

    hdfs://nn2:8020/bar 
    hdfs://nn2:8020/bar/aa 32 
    hdfs://nn2:8020/bar/ba 32 
    hdfs://nn2:8020/bar/bb 64

會產生:

    hdfs://nn2:8020/bar 
    hdfs://nn2:8020/bar/aa 32 
    hdfs://nn2:8020/bar/ab 32 
    hdfs://nn2:8020/bar/ba 64 
    hdfs://nn2:8020/bar/bb 32

只有nn2aa文件沒有被覆蓋。如果指定了 -overwrite選項,所有文件都會被覆蓋。

 

補充說明:

1.SSL Configurations for HSFTP sources

To use an HSFTP source (i.e. using the hsftp protocol), a Map-Red SSL configuration file needs to be specified (via the -mapredSslConf option). This must specify 3 parameters:

 

ssl.client.truststore.location: The local-filesystem location of the trust-store file, containing the certificate for the namenode.

ssl.client.truststore.type: (Optional) The format of the trust-store file.

ssl.client.truststore.password: (Optional) Password for the trust-store file.

The following is an example of the contents of the contents of a Map-Red SSL Configuration file:

 

 

<configuration>

<property>

<name>ssl.client.truststore.location</name>

<value>/work/keystore.jks</value>

<description>Truststore to be used by clients like distcp. Must be specified. </description>

</property>

<property>

<name>ssl.client.truststore.password</name>

<value>changeme</value>

<description>Optional. Default value is "". </description>

</property>

 

<property>

<name>ssl.client.truststore.type</name>

<value>jks</value>

<description>Optional. Default value is "jks". </description>

</property>

</configuration>

 

 

The SSL configuration file must be in the class-path of the DistCp program.

 

2.在不同HDFS版本複製

對於在兩個不同版本的Hadoop之間進行復制,通常使用HftpFileSystem。這是一個只讀文件系統,因此DistCp必須在目標集羣上運行(更具體地說,在可以寫入目標集羣的TaskTracker上)。每個源都指定爲

hftp// <dfs.http.address> / <path> 

(默認dfs.http.address是<namenode>50070)。

 

附錄

Map數目

DistCp會嘗試着均分需要拷貝的內容,這樣每個map拷貝差不多相等大小的內容。 但因爲文件是最小的拷貝粒度,所以配置增加同時拷貝(如map)的數目不一定會增加實際同時拷貝的數目以及總吞吐量。

如果沒使用-m選項,DistCp會嘗試在調度工作時指定map的數目 爲 min (total_bytes / bytes.per.map, 20 * num_task_trackers), 其中bytes.per.map默認是256MB建議對於長時間運行或定期運行的作業,根據源和目標集羣大小、拷貝數量大小以及帶寬調整map的數目。

不同HDFS版本間的拷貝

對於不同Hadoop版本間的拷貝,用戶應該使用HftpFileSystem。 這是一個只讀文件系統,所以DistCp必須運行在目標端集羣上(更確切的說是在能夠寫入目標集羣的TaskTracker上)。 源的格式是hftp://<dfs.http.address>/<path> (默認情況dfs.http.address是 <namenode>:50070)。

Map/Reduce和副效應

像前面提到的,map拷貝輸入文件失敗時,會帶來一些副效應。

1. 除非使用了-i,任務產生的日誌會被新的嘗試替換掉。

2. 除非使用了-overwrite,文件被之前的map成功拷貝後當又一次執行拷貝時會被標記爲 "被忽略"

3. 如果map失敗了mapred.map.max.attempts次,剩下的map任務會被終止(除非使用了-i)

4. 如果mapred.speculative.execution被設置爲 final和true,則拷貝的結果是未定義的。

 

Frequently Asked Questions

1.Why does -update not create the parent source-directory under a pre-existing target directory?

The behaviour of -update and -overwrite is described in detail in the Usage section of this document. In short, if either option is used with a pre-existing destination directory, the contents of each source directory is copied over, rather than the source-directory itself. This behaviour is consistent with the legacy DistCp implementation as well.

 

2.How does the new DistCp differ in semantics from the Legacy DistCp?

Files that are skipped during copy used to also have their file-attributes (permissions, owner/group info, etc.) unchanged, when copied with Legacy DistCp. These are now updated, even if the file-copy is skipped.

Empty root directories among the source-path inputs were not created at the target, in Legacy DistCp. These are now created.

 

3.Why does the new DistCp use more maps than legacy DistCp?

Legacy DistCp works by figuring out what files need to be actually copied to target before the copy-job is launched, and then launching as many maps as required for copy. So if a majority of the files need to be skipped (because they already exist, for example), fewer maps will be needed. As a consequence, the time spent in setup (i.e. before the M/R job) is higher.

 

The new DistCp calculates only the contents of the source-paths. It doesn't try to filter out what files can be skipped. That decision is put- off till the M/R job runs. This is much faster (vis-a-vis execution-time), but the number of maps launched will be as specified in the -m option, or 20 (default) if unspecified.

 

4.Why does DistCp not run faster when more maps are specified?

At present, the smallest unit of work for DistCp is a file. i.e., a file is processed by only one map. Increasing the number of maps to a value exceeding the number of files would yield no performance benefit. The number of maps lauched would equal the number of files.

 

5.Why does DistCp run out of memory?

If the number of individual files/directories being copied from the source path(s) is extremely large (e.g. 1,000,000 paths), DistCp might run out of memory while determining the list of paths for copy. This is not unique to the new DistCp implementation.

To get around this, consider changing the -Xmx JVM heap-size parameters, as follows:

 

bash$ export HADOOP_CLIENT_OPTS="-Xms64m -Xmx1024m"

bash$ hadoop distcp2 /source /target

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章