通過distcp進行並行復制
前面的HDFS訪問模型都集中於單線程的訪問。例如通過指定文件通配,我們可以對一部分文件進行處理,但是為了高效,對這些文件的並行處理需要新寫一個程序。Hadoop有一個叫distcp(分布式復制)的有用程序,能從Hadoop的文件系統並行復制大量數據。
distcp一般用於在兩個HDFS集群中傳輸數據。如果集群在Hadoop的同一版本上運行,就適合使用hdfs方案:
% hadoop distcp hdfs://namenode1/foo hdfs://namenode2/bar
這將從第一個集群中復制/foo目錄(和它的內容)到第二個集群中的/bar目錄下,所以第二個集群會有/bar/foo目錄結構。如果/bar不存在,則新建一個。我們可以指定多個源路徑,並且所有的都會被復制到目標路徑。源路徑必須是絕對路徑。
默認情況下,distcp會跳過目標路徑已經有的文件,但可以通過提供的-overwrite選項進行覆蓋。也可以用-update選項來選擇只更新那些修改過的文件。
注意:使用-overwrite和-update中任意一個(或兩個)選項會改變源路徑和目標路徑的含義。這可以用一個例子清楚說明。如果改變先前例子中第一個集群的子樹/foo下的一個文件,就能通過運行對第二個集群的改變進行同步:
% hadoop distcp -update hdfs://namenode1/foo hdfs://namenode2/bar/foo
目標路徑需要末尾這個額外的子目錄/foo,因為源目錄下的內容已被復制到目標目錄下。(如果熟悉rsync,你可以想像-overwrite或-update項對源路徑而言,如同添加一個隱含的斜杠。)
如果對discp操作不是很確定,最好先對一個小的測試目錄樹進行嘗試。
有很多選項可以控制分布式復制行為,包括預留文件屬性,忽略故障和限制復制的文件或總數據的數量。運行時不帶任何選項,可以看到使用說明。
distcp是作為一個MapReduce作業執行的,復制工作由集群中並行運行的map來完成。這里並沒有reducer。每個文件都由一個單一的map進行復制,並且distcp通過將文件分成大致相等的文件來為每個map數量大致相同的數據。
map的數量是這樣確定的。通過讓每一個map復制數量合理的數據以最小化任務建立所涉及的開銷,是一個很好的想法,所以每個map的副本至少為256 MB。(除非輸入的總大小較少,否則一個map就足以操控全局。)例如,1 GB的文件會被分成4個map任務。如果數據很大,為限制帶寬和集群的使用而限制映射的數量就變得很有必要。map默認的最大數量是每個集群節點(tasktracker)有20個。例如,復制1000 GB的文件到一個100個節點的集群,會分配2000個map(每個節點20個map),所以平均每個會復制512 MB。通過對distcp指定-m參數,會減少映射的分配數量。例如,-m 1000會分配1000個map,平均每個復制1 GB。
如果想在兩個運行着不同版本HDFS的集群上利用distcp,使用hdfs協議是會失敗的,因為RPC系統是不兼容的。想要彌補這種情況,可以使用基於HTTP的HFTP文件系統從源中進行讀取。這個作業必須運行在目標集群上,使得HDFS RPC版本是兼容的。使用HFTP重復前面的例子:
% hadoop distcp hftp://namenode1:50070/foo hdfs://namenode2/bar
注意,需要在URI源中指定名稱節點的Web端口。這是由dfs.http.address的屬性決定的,默認值為50070。
保持HDFS集群的平衡
向HDFS復制數據時,考慮集群的平衡相當重要。文件塊在集群中均勻地分布時,HDFS能達到最佳工作狀態。回顧前面1000 GB數據的例子,通過指定-m選項為1,即由一個單一的map執行復制工作,它的意思是,不考慮速度變慢和未充分利用集群資源,每個塊的第一個副本會存儲在運行map的節點上(直到磁盤被填滿)。第二和第三個副本分散在集群中,但這一個節點並不會平衡。通過讓map的數量多於集群中節點的數量,我們便可避免這個問題。鑒於此,最好首先就用默認的每個節點20個map這個默認設置來運行distcp。
然而,這也並不總能阻止一個集群變得不平衡。也許想限制map的數量以便一些節點可以被其他作業使用。若是這樣,可以使用balancer工具(參見第10章)繼續改善集群中塊的分布
前面的HDFS訪問模型都集中於單線程的訪問。例如通過指定文件通配,我們可以對一部分文件進行處理,但是為了高效,對這些文件的並行處理需要新寫一個程序。Hadoop有一個叫distcp(分布式復制)的有用程序,能從Hadoop的文件系統並行復制大量數據。
distcp一般用於在兩個HDFS集群中傳輸數據。如果集群在Hadoop的同一版本上運行,就適合使用hdfs方案:
% hadoop distcp hdfs://namenode1/foo hdfs://namenode2/bar
這將從第一個集群中復制/foo目錄(和它的內容)到第二個集群中的/bar目錄下,所以第二個集群會有/bar/foo目錄結構。如果/bar不存在,則新建一個。我們可以指定多個源路徑,並且所有的都會被復制到目標路徑。源路徑必須是絕對路徑。
默認情況下,distcp會跳過目標路徑已經有的文件,但可以通過提供的-overwrite選項進行覆蓋。也可以用-update選項來選擇只更新那些修改過的文件。
注意:使用-overwrite和-update中任意一個(或兩個)選項會改變源路徑和目標路徑的含義。這可以用一個例子清楚說明。如果改變先前例子中第一個集群的子樹/foo下的一個文件,就能通過運行對第二個集群的改變進行同步:
% hadoop distcp -update hdfs://namenode1/foo hdfs://namenode2/bar/foo
目標路徑需要末尾這個額外的子目錄/foo,因為源目錄下的內容已被復制到目標目錄下。(如果熟悉rsync,你可以想像-overwrite或-update項對源路徑而言,如同添加一個隱含的斜杠。)
如果對discp操作不是很確定,最好先對一個小的測試目錄樹進行嘗試。
有很多選項可以控制分布式復制行為,包括預留文件屬性,忽略故障和限制復制的文件或總數據的數量。運行時不帶任何選項,可以看到使用說明。
distcp是作為一個MapReduce作業執行的,復制工作由集群中並行運行的map來完成。這里並沒有reducer。每個文件都由一個單一的map進行復制,並且distcp通過將文件分成大致相等的文件來為每個map數量大致相同的數據。
map的數量是這樣確定的。通過讓每一個map復制數量合理的數據以最小化任務建立所涉及的開銷,是一個很好的想法,所以每個map的副本至少為256 MB。(除非輸入的總大小較少,否則一個map就足以操控全局。)例如,1 GB的文件會被分成4個map任務。如果數據很大,為限制帶寬和集群的使用而限制映射的數量就變得很有必要。map默認的最大數量是每個集群節點(tasktracker)有20個。例如,復制1000 GB的文件到一個100個節點的集群,會分配2000個map(每個節點20個map),所以平均每個會復制512 MB。通過對distcp指定-m參數,會減少映射的分配數量。例如,-m 1000會分配1000個map,平均每個復制1 GB。
如果想在兩個運行着不同版本HDFS的集群上利用distcp,使用hdfs協議是會失敗的,因為RPC系統是不兼容的。想要彌補這種情況,可以使用基於HTTP的HFTP文件系統從源中進行讀取。這個作業必須運行在目標集群上,使得HDFS RPC版本是兼容的。使用HFTP重復前面的例子:
% hadoop distcp hftp://namenode1:50070/foo hdfs://namenode2/bar
注意,需要在URI源中指定名稱節點的Web端口。這是由dfs.http.address的屬性決定的,默認值為50070。
保持HDFS集群的平衡
向HDFS復制數據時,考慮集群的平衡相當重要。文件塊在集群中均勻地分布時,HDFS能達到最佳工作狀態。回顧前面1000 GB數據的例子,通過指定-m選項為1,即由一個單一的map執行復制工作,它的意思是,不考慮速度變慢和未充分利用集群資源,每個塊的第一個副本會存儲在運行map的節點上(直到磁盤被填滿)。第二和第三個副本分散在集群中,但這一個節點並不會平衡。通過讓map的數量多於集群中節點的數量,我們便可避免這個問題。鑒於此,最好首先就用默認的每個節點20個map這個默認設置來運行distcp。
然而,這也並不總能阻止一個集群變得不平衡。也許想限制map的數量以便一些節點可以被其他作業使用。若是這樣,可以使用balancer工具(參見第10章)繼續改善集群中塊的分布