Hadoop源生實用工具之distcp
1 概覽
DistCp(Distributed Copy)是用於大規模叢集內部或者叢集之間的高效能拷貝工具。 它使用Map/Reduce實現檔案分發,錯誤處理和恢復,以及報告生成。 它把檔案和目錄的列表作為map任務的輸入,每個任務會完成源列表中部分檔案的拷貝
備註:在工作中遇到部門間資料合作,誇不同叢集版本或者同版本不同叢集的資料copy是不同的。
2 實用
總體來說分兩類:
1) 同版本叢集間資料copy ;
2) 誇叢集版本資料copy;
同版本叢集間資料copy
比如:拷貝A叢集(nn1的IP192.168.7.120)的A目錄到B叢集(nn2的IP192.168.8.120)的B1目錄
1 hadoop distcp hdfs://192.168.7.120:8020/cluster/A/ hdfs://192.168.8.120:8020/cluster/B1/
小結:
a) 使用hdfs協議,其中192.168.7.120是A叢集的namenode地址, 8020是A叢集的rpc埠(hdfs-site.xml中可檢視)。192.168.8.120是B叢集的namenode IP地址
b) 這條命令會將A叢集中的/A資料夾以及資料夾下的檔案複製到B叢集中的/B1目錄下,即在B叢集中會以/B1/A的目錄結構出現。如果/B1目錄不存在,則系統會新建一個。需要注意的是,源路徑必須是絕對路徑。包含前面的hdfs://ip:port
新增多個數據源,指定多個源目錄 如:
1 hadoop distcp hdfs: 2 3 //192.168.7.120:8020/cluster/A/a1 hdfs://192.168.7.120:8020/A/a2 hdfs://192.168.8.120:8020/cluster/B1/
或者使用-f選項,從檔案裡獲得多個源:
hadoop distcp -f hdfs://192.168.7.120:8020/src_A_list hdfs://192.168.8.120:8020/cluster/B1/
其中src_A_list 的內容是
hdfs://192.168.7.120:8020/cluster/A/a1
hdfs://192.168.7.120:8020/cluster/A/a2
當從多個源拷貝時,如果兩個源衝突,distcp會停止拷貝並提示出錯資訊, 如果在目的位置發生衝突,會根據選項設定解決。 預設情況會跳過已經存在的目標檔案(c處說明;比如不用原始檔做替換操作)。每次操作結束時 都會報告跳過的檔案數目,但是如果某些拷貝操作失敗了,但在之後的嘗試成功了, 那麼報告的資訊可能不夠精確。
每個JobTracker必須都能夠與源端和目的端檔案系統進行訪問和互動。
拷貝完成後,建議生成源端和目的端檔案的列表,並交叉檢查,來確認拷貝真正成功。 因為distcp使用Map/Reduce和檔案系統API進行操作,所以這三者或它們之間有任何問題 可能影響拷貝。
值得注意的是,當另一個客戶端同時在向原始檔寫入時,拷貝很有可能會失敗。 嘗試覆蓋HDFS上正在被寫入的檔案的操作也會失敗。 如果一個原始檔在拷貝之前被移動或刪除了,拷貝失敗同時輸出異常 FileNotFoundException。
c) 預設情況下,雖然distcp會跳過在目標路徑上已經存在的檔案,但是通過-overwirte選項可以選擇對這些檔案進行覆蓋重寫,也可以使用,-update選項僅對更新過的檔案進行重寫。
實戰案例:
案例要求 從/cluster/A1/ 和 /cluster/A2/ 到 /cluster/B1的拷貝,源路徑包括: hdfs://192.168.7.120:8020/cluster/A1 hdfs://192.168.7.120:8020/cluster/A1/a1 hdfs://192.168.7.120:8020/cluster/A1/a2 hdfs://192.168.7.120:8020/cluster/A2 hdfs://192.168.7.120:8020/cluster/A2/a3 hdfs://192.168.7.120:8020/cluster/A2/a1
如果沒設定-update或 -overwrite選項, 那麼兩個源都會對映到目標端的 /cluster/B1/A1A2。 如果設定了這兩個選項,每個源目錄的內容都會和目標目錄的 內容 做比較。distcp碰到這類衝突的情況會終止操作並退出。 預設情況下,/cluster/B1/A1 和 /cluster/B1/A2 目錄都會被建立,所以並不會有衝突。 現在講-update用法: distcp -update hdfs://192.168.7.120:8020/cluster/A1 \ hdfs://192.168.7.120:8020/cluster/A2 \ hdfs://192.168.8.120:8020/cluster/B1 其中源路徑/大小: hdfs://192.168.7.120:8020/cluster/A1 hdfs://192.168.7.120:8020/cluster/A1/a1 32 hdfs://192.168.7.120:8020/cluster/A1/a2 64 hdfs://192.168.7.120:8020/cluster/A2 hdfs://192.168.7.120:8020/cluster/A2/a3 64 hdfs://192.168.7.120:8020/cluster/A2/a4 32 和目的路徑/大小: hdfs://192.168.8.120:8020/cluster/B1 hdfs://192.168.8.120:8020/cluster/B1/a1 32 hdfs://192.168.8.120:8020/cluster/B1/a2 32 hdfs://192.168.8.120:8020/cluster/B1/a3 128 會產生: hdfs://192.168.8.120:8020/cluster/B1 hdfs://192.168.8.120:8020/cluster/B1/a1 32 hdfs://192.168.8.120:8020/cluster/B1/a2 32 hdfs://192.168.8.120:8020/cluster/B1/a3 64 hdfs://192.168.8.120:8020/cluster/A2/a4 32 發現部分192.168.8.120的a2檔案沒有被覆蓋(a3卻覆蓋)。如果指定了 -overwrite選項,所有檔案都會被覆蓋。
d) distcp操作有很多選項可以設定,比如忽略失敗、限制檔案或者複製的資料量等。直接輸入指令或者不附加選項則可以檢視此操作的使用說明。
附件distcp可以選配的引數:
誇叢集版本資料copy
hadoop distcp hftp://192.168.7.120:50070/cluster/A/ hdfs://192.168.8.120:8020/cluster/B1
需要注意的是,要定義訪問源的URI中NameNode的網路介面,這個介面會通過dfs.namenode.http-address的屬性值設定,預設值為50070 ,參考hdfs-site.xml:
3 實戰出現的問題總結
a)ipc.StandbyException : //s.apache.org/sbnn-error
解決:
Dfs所連結的namenode的狀態不是active的 處於standby狀態不予連結,所以方法:換一個namenode, 保證新的namenode是active
b) java.io.IOException:Check-sum mismatch
分析:該問題很常見,能在網上查到,是因為不同版本hadoop 的checksum版本不同,老版本用crc32,新版本用crc32c;
解決:只要在distcp時增加兩個引數(-skipcrccheck -update),忽略crc檢查即可。注意-skipcrccheck引數要與-update同時使用才生效。
c) java.net.UnknowHostException
原因分析:圖中可以看到,distcp job已經啟動了,map 0%, 但是報了UnknowHostException:pslaves55,可能的原因是在從datanode取資料時,用的是host pslave55, 而這個host是資料來源叢集特有的,目標叢集不識別,所以報UnknowHostException.
解決辦法:在目標叢集中配置hosts檔案,將資料來源叢集中所有的host和ip的對應關係追加到目標叢集中的hosts檔案中,使得目標叢集在訪問host名時(如pslave55)能成功對映到ip
4 總結
要實現跨叢集拷貝,如拷貝A叢集的資料到B叢集,需要確認以下事情:
(1)確認B叢集機器都能ping通A叢集所有ip。
(2) 用的port 響應在各自節點上放開 iptables 不要“攔住”
(3)如果部門間的埠防火牆已經開通,但還是telnet不同,請確認A叢集的iptables已經加入了B叢集ip。
(4)如果在B叢集有UnknowHostException,則需要將A叢集的host與ip對映關係追加到B叢集的hosts檔案中。
附上常用埠port 對照:
其他配置參考官方:
http://hadoop.apache.org/docs/r2.7.6/hadoop-distcp/DistCp.html
&n