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
覆寫目标
-update
如果源和目标的大小不一樣則進行覆寫
-f <urilist_uri>
使用<urilist_uri> 作為源檔案清單
這等價于把所有檔案名列在指令行中。 urilist_uri 清單應該是完整合法的URI。
這裡給出一些 -update和 -overwrite的例子。 考慮一個從/foo/a 和 /foo/b 到 /bar/foo的拷貝,源路徑包括:
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/aa 32
hdfs://master1:8020/foo/a/ab 32
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/ab 32
hdfs://master2:8020/bar/ba 64
hdfs://master2:8020/bar/bb 32
隻有master2的aa檔案沒有被覆寫。如果指定了 -overwrite選項,所有檔案都會被覆寫。
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
對于不同Hadoop版本間的拷貝,使用者應該使用HftpFileSystem。 這是一個隻讀檔案系統,是以distcp必須運作在目标端叢集上(更确切的說是在能夠寫入目标叢集的TaskTracker上)。 源的格式是 hftp://<dfs.http.address>/<path> (預設情況dfs.http.address是 <namenode>:50070)。
像前面提到的,map拷貝輸入檔案失敗時,會帶來一些副效應。
除非使用了-i,任務産生的日志會被新的嘗試替換掉。
除非使用了-overwrite,檔案被之前的map成功拷貝後當又一次執行拷貝時會被标記為 "被忽略"。
如果map失敗了mapred.map.max.attempts次,剩下的map任務會被終止(除非使用了-i)。
如果mapred.speculative.execution被設定為 final和true,則拷貝的結果是未定義的。
文章可以轉載,必須以連結形式标明出處。
本文轉自 張沖andy 部落格園部落格,原文連結: http://www.cnblogs.com/andy6/p/7490599.html ,如需轉載請自行聯系原作者