hadoop之 distcp(分布式拷貝)


概述

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

 

基本使用方法

distcp最常用在集群之間的拷貝:

 hadoop distcp hdfs://master1:8020/foo/bar hdfs://master2:8020/bar/foo

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

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

 hadoop distcp hdfs://master1:8020/foo/a hdfs://master1:8020/foo/b hdfs://master2:8020/bar/foo

或者使用-f選項,從文件里獲得多個源:
 hadoop distcp -f hdfs://master1:8020/srclist hdfs://master2:8020/bar/foo 

其中srclist 的內容是
    hdfs://master1:8020/foo/a 
    hdfs://master1: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。

更新和覆蓋

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

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

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

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

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

其中源路徑/大小:

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

和目的路徑/大小:

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

會產生:

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

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

附錄

Map數目

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

如果沒使用-m選項,distcp會嘗試在調度工作時指定map的數目 為 min (total_bytes / bytes.per.map, 20 * num_task_trackers), 其中bytes.per.map默認是256MB。

建議對於長時間運行或定期運行的作業,根據源和目標集群大小、拷貝數量大小以及帶寬調整map的數目。

hadoop distcp -Ddistcp.bytes.per.map=1073741824 -Ddfs.client.socket-timeout=240000000 -Dipc.client.connect.timeout=40000000 -i -update  hdfs://master1:8020/foo/a hdfs://master1:8020/foo/b hdfs://master2:8020/bar/foo

不同HDFS版本間的拷貝

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

Map/Reduce和副效應

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

  • 除非使用了-i,任務產生的日志會被新的嘗試替換掉。
  • 除非使用了-overwrite,文件被之前的map成功拷貝后當又一次執行拷貝時會被標記為 "被忽略"。
  • 如果map失敗了mapred.map.max.attempts次,剩下的map任務會被終止(除非使用了-i)。
  • 如果mapred.speculative.execution被設置為 final和true,則拷貝的結果是未定義的。
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM