天天看點

[Hadoop]資料複制DistCp

版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。 https://blog.csdn.net/SunnyYoona/article/details/54668028

1.需求

我們項目中需要複制一個大檔案,最開始使用的是hadoop cp指令,但是随着檔案越來越大,拷貝的時間也水漲船高。下面進行hadoop cp與hadoop distcp拷貝時間上的一個對比。我們将11.9G的檔案從data_group/adv/day=20170116下所有檔案複制到tmp/data_group/adv/day=20170116/檔案下

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#11-%E6%9F%A5%E7%9C%8B%E6%96%87%E4%BB%B6%E5%A4%A7%E5%B0%8F 1.1 檢視檔案大小

hadoop fs -du -s -h data_group/adv/day=20170116
11.9 G  data_group/adv/day=20170116           

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#12-%E5%A4%8D%E5%88%B6 1.2 複制

hadoop distcp data_group/adv/day=20170116 \
tmp/data_group/adv/day=20170116 

hadoop fs -cp data_group/adv/day=20170116 \
tmp/data_group/adv/day=2010116           

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#13-%E5%AF%B9%E6%AF%94 1.3 對比

使用distcp指令 僅耗時1分鐘;而hadoop cp指令耗時14分鐘

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#2-%E6%A6%82%E8%BF%B0 2. 概述

DistCp(分布式拷貝)是用于大規模叢集内部和叢集之間拷貝的工具。 它使用Map/Reduce實作檔案分發,錯誤處理和恢複,以及報告生成。 它把檔案和目錄的清單作為map任務的輸入,每個任務會完成源清單中部分檔案的拷貝。 由于使用了Map/Reduce方法,這個工具在語義和執行上都會有特殊的地方。

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#21-distcp%E5%91%BD%E4%BB%A4-%E8%BE%93%E5%87%BA 2.1 distcp指令 輸出

17/01/19 14:30:07 INFO tools.DistCp: Input Options: DistCpOptions{atomicCommit=false, syncFolder=false, deleteMissing=false, ignoreFailures=false, maxMaps=20, sslConfigurationFile='null', copyStrategy='uniformsize', sourceFileListing=null, sourcePaths=[data_group/adv/day=20170116], targetPath=tmp/data_group/adv/day=20170116}
...
17/01/19 14:30:17 INFO mapreduce.Job:  map 0% reduce 0%
17/01/19 14:30:29 INFO mapreduce.Job:  map 6% reduce 0%
17/01/19 14:30:34 INFO mapreduce.Job:  map 41% reduce 0%
17/01/19 14:30:35 INFO mapreduce.Job:  map 94% reduce 0%
17/01/19 14:30:36 INFO mapreduce.Job:  map 100% reduce 0%
17/01/19 14:31:34 INFO mapreduce.Job: Job job_1472052053889_8081193 completed successfully
17/01/19 14:31:34 INFO mapreduce.Job: Counters: 30
        File System Counters
                FILE: Number of bytes read=0
                FILE: Number of bytes written=1501420
                FILE: Number of read operations=0
                FILE: Number of large read operations=0
                FILE: Number of write operations=0
                HDFS: Number of bytes read=12753350866
                HDFS: Number of bytes written=12753339159
                HDFS: Number of read operations=321
                HDFS: Number of large read operations=0
                HDFS: Number of write operations=69
        Job Counters 
                Launched map tasks=17
                Other local map tasks=17
                Total time spent by all maps in occupied slots (ms)=485825
                Total time spent by all reduces in occupied slots (ms)=0
        Map-Reduce Framework
                Map input records=17
                Map output records=0
                Input split bytes=2414
                Spilled Records=0
                Failed Shuffles=0
                Merged Map outputs=0
                GC time elapsed (ms)=1634
                CPU time spent (ms)=156620
                Physical memory (bytes) snapshot=5716221952
                Virtual memory (bytes) snapshot=32341671936
                Total committed heap usage (bytes)=12159811584
        File Input Format Counters 
                Bytes Read=9293
        File Output Format Counters 
                Bytes Written=0
        org.apache.hadoop.tools.mapred.CopyMapper$Counter
                BYTESCOPIED=12753339159
                BYTESEXPECTED=12753339159
                COPY=17           

是不是很熟悉,這就是我們經常看見到的MapReduce任務的輸出資訊,這從側面說明了Distcp使用Map/Reduce實作。

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#3-%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95 3. 使用方法

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#31-%E9%9B%86%E7%BE%A4%E9%97%B4%E6%8B%B7%E8%B4%9D 3.1 叢集間拷貝

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

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

這條指令會把nn1叢集的/foo/bar目錄下的所有檔案以及bar本身目錄(預設情況下)存儲到一個臨時檔案中,這些檔案内容的拷貝工作被配置設定給多個map任務, 然後每個TaskTracker分别執行從nn1到nn2的拷貝操作。注意DistCp使用絕對路徑進行操作。

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#32-%E9%9B%86%E7%BE%A4%E5%86%85%E9%83%A8%E6%8B%B7%E8%B4%9D 3.2 叢集内部拷貝

DistCp也可以叢集内部之間的拷貝:

hadoop distcp tmp/data_group/test/a 
    tmp/data_group/test/target           

這條指令會把本叢集tmp/data_group/test/a目錄本身以及a目錄下的所有檔案拷貝到target目錄下,原理同叢集之間的拷貝一樣。

備注

hadoop distcp tmp/data_group/test/a 
    tmp/data_group/test/target           

上述指令預設情況下是複制a目錄以及a目錄下所有檔案到target目錄下:

hadoop fs -ls -R tmp/data_group/test/target/

tmp/data_group/test/target/aa
tmp/data_group/test/target/aa/aa.txt
tmp/data_group/test/target/aa/ab.txt           

而有時我們的需求是複制a目錄下的所有檔案而不包含a目錄,這時可以後面介紹的-update參數:

hadoop distcp -update tmp/data_group/test/aa tmp/data_group/test/target
...
hadoop fs -ls -R tmp/data_group/test/target/

tmp/data_group/test/target/aa/aa.txt
tmp/data_group/test/target/aa/ab.txt           

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#33-%E5%A4%9A%E6%BA%90%E7%9B%AE%E5%BD%95 3.3 多源目錄

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

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

或者使用-f選項,從檔案裡獲得多個源:

hadoop distcp -f hdfs://nn1:8020/srclist \
    hdfs://nn2:8020/bar/foo           

其中srclist 的内容是

hdfs://nn1:8020/foo/a 
hdfs://nn1:8020/foo/b           

當從多個源拷貝時,如果兩個源沖突,DistCp會停止拷貝并提示出錯資訊

Example:

hadoop distcp tmp/data_group/tes
t/source_new/aa.txt tmp/data_group/test/source_old/aa.txt tmp/data_group/test/target           

我們分别複制source_new和source_old目錄下的aa.txt檔案到target檔案夾下,報錯如下:

17/01/21 15:15:05 ERROR tools.DistCp: Duplicate files in input path: 
org.apache.hadoop.tools.CopyListing$DuplicateFileException: File hdfs://XXX/user/XXX/tmp/data_group/test/source_new/aa.txt and \
hdfs://XXX/user/XXX/tmp/data_group/test/source_old/aa.txt would cause duplicates. Aborting
        at org.apache.hadoop.tools.CopyListing.checkForDuplicates(CopyListing.java:151)
        at org.apache.hadoop.tools.CopyListing.buildListing(CopyListing.java:87)
        at org.apache.hadoop.tools.GlobbedCopyListing.doBuildListing(GlobbedCopyListing.java:90)
        at org.apache.hadoop.tools.CopyListing.buildListing(CopyListing.java:80)
        at org.apache.hadoop.tools.DistCp.createInputFileListing(DistCp.java:327)
        at org.apache.hadoop.tools.DistCp.execute(DistCp.java:151)           

如果在目的位置發生沖突,會根據選項設定解決。 預設情況會跳過已經存在的目标檔案(比如不用源檔案做替換操作)。每次操作結束時 都會報告跳過的檔案數目,但是如果某些拷貝操作失敗了,但在之後的嘗試成功了, 那麼報告的資訊可能不夠精确(請參考附錄)。

每個TaskTracker必須都能夠與源端和目的端檔案系統進行通路和互動。 對于HDFS來說,源和目的端要運作相同版本的協定或者使用向下相容的協定。 (請參考不同版本間的拷貝 )。

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

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

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#4-%E9%80%89%E9%A1%B9 4. 選項

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#41-i-%E5%BF%BD%E7%95%A5%E5%A4%B1%E8%B4%A5 4.1 -i 忽略失敗

這個選項會比預設情況提供關于拷貝的更精确的統計, 同時它還将保留失敗拷貝操作的日志,這些日志資訊可以用于調試。最後,如果一個map失敗了,但并沒完成所有分塊任務的嘗試,這不會導緻整個作業的失敗。

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#42-log-logdir-%E8%AE%B0%E5%BD%95%E6%97%A5%E5%BF%97 4.2 -log <logdir> 記錄日志

DistCp為每個檔案的每次嘗試拷貝操作都記錄日志,并把日志作為map的輸出。 如果一個map失敗了,當重新執行時這個日志不會被保留。

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#43-overwrite-%E8%A6%86%E7%9B%96%E7%9B%AE%E6%A0%87 4.3 -overwrite 覆寫目标

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

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#44-update-%E6%BA%90%E5%92%8C%E7%9B%AE%E6%A0%87%E7%9A%84%E5%A4%A7%E5%B0%8F%E4%B8%8D%E4%B8%80%E6%A0%B7%E5%88%99%E8%BF%9B%E8%A1%8C%E8%A6%86%E7%9B%96 4.4 -update 源和目标的大小不一樣則進行覆寫

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

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#5-%E6%9B%B4%E6%96%B0%E4%B8%8E%E8%A6%86%E7%9B%96 5. 更新與覆寫

這裡給出一些 -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合法的操作:

hadoop distcp -update tmp/data_group/test/source/ \ 
               tmp/data_group/test/target/           

其中源路徑/大小:

11 tmp/data_group/test/source/aa.txt
23 tmp/data_group/test/source/ab.txt
34 tmp/data_group/test/source/ba.txt           

和目的路徑/大小:

11 tmp/data_group/test/target/aa.txt
9  tmp/data_group/test/target/ba.txt           

會産生:

11 tmp/data_group/test/target/aa.txt
23 tmp/data_group/test/target/ab.txt
34 tmp/data_group/test/target/ba.txt           

隻有target目錄的aa.txt檔案沒有被覆寫。上面以及提到過,update不是"同步"操作。執行覆寫的唯一标準是源檔案和目标檔案大小是否相同;如果不同,則源檔案替換目标檔案。source中的aa.txt大小與target中的aa.txt大小一樣,是以不會覆寫。

實際測試的過程中,target目錄下的aa.txt也會被覆寫,不得其解。求解......

如果指定了 -overwrite選項,所有檔案都會被覆寫。

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#6-map%E6%95%B0%E7%9B%AE 6. Map數目

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

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

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

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#7%E4%B8%8D%E5%90%8Chdfs%E7%89%88%E6%9C%AC%E9%97%B4%E7%9A%84%E6%8B%B7%E8%B4%9D 7.不同HDFS版本間的拷貝

對于不同Hadoop版本間的拷貝,使用者應該使用HftpFileSystem。 這是一個隻讀檔案系統,是以DistCp必須運作在目标端叢集上(更确切的說是在能夠寫入目标叢集的TaskTracker上)。 源的格式是 hftp://<dfs.http.address>/<path> (預設情況dfs.http.address是 <namenode>:50070)。

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEBe5d7ebdffb4406b964a7c900fadc8cdc%3Fmethod%3Ddownload%26read%3Dtrue#8-mapreduce%E5%92%8C%E5%89%AF%E6%95%88%E5%BA%94 8. Map/Reduce和副效應

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

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