Hadoop學習筆記 - Sort / TeraSort / TestDFSIO

彩色螞蟻發表於2012-08-10

Hadoop Examples學習筆記

作者:劉旭暉Raymond轉載請註明出處

Email:colorant@163.com

BLOG:http://blog.csdn.net/colorant/

 

記錄一下這幾天學習Hadoop的幾個測試用例的理解。主要是三個Sort/TeraSort/TestDFSIO, 這幾個example一方面可以用來做benchmark,另一方面通過學習閱讀,也有助於理解Hadoop的MR框架 ;) 

Sort : org.apache.hadoop.examples.Sort

功能目的

Sort的功能就是對輸入檔案按Key進行排序。預設處理格式為<text,text> pair的Sequence File。

流程分析

如果不考慮全排序功能的話,Sort本身的實現是相當簡單的,Map和Reduce階段都採用Hadoop自帶的IdentityMapper/Reducer,即不對資料做任何處理,直接輸出。完全利用Hadoop Framework在Map的output階段和Reduce階段的排序功能對key值進行排序

相關思考

如果不使用TotalOrder,Sort的輸出結果中,每個Reduce Task的輸出是區域性排序的,但是各個Reduce Task的輸出結果之間是沒有經過全域性排序過的。這是因為在partition階段對<K,V>只是簡單的按key的hash結果來分配資料。

 

TeraSort: org.apache.hadoop.examples.terasort.TeraSort

功能目的  

對輸入檔案按Key進行全域性排序。另外TeraSort針對的是大批量的資料,在實現過程中為了保證Reduce階段各個Reduce Job的負載平衡,以保證全域性運算的速度,TeraSort對資料進行了預取樣分析。

流程分析  

從job框架上看,為了保證Reduce階段的負載平衡,使用jobConf.setPartitionerClass自定義了Partitioner Class用來對資料進行分割槽,在map和reduce階段對資料不做額外處理。Job流程如下:

 

•       對資料進行分段取樣:例如將輸入檔案最多分割為10段,每段讀取最多100,000行資料作為樣本,統計各個Key值出現的頻率並對Key值使用內建的QuickSort進行快速排序(這一步是JobClient在單個節點上執行的,取樣的運算量不能太大)

 

•       將樣本統計結果中位於樣本統計平均分段處的Key值(例如n/10處 n=[1..10])做為分割槽的依據以DistributedCache的方式寫入檔案,這樣在MapReduce階段的各個節點都能夠Access這個檔案。如果全域性資料的Key值分佈與樣本類似的話,這也就代表了全域性資料的平均分割槽的位置。(所以取樣的數量也不能太小)

 

•       在MapReduceJob執行過程中,自定義的Partitioner會讀取這個樣本統計檔案,根據分割槽邊界Key值建立一個兩級的索引樹用來快速定位特定Key值對應的分割槽(這個兩級索引樹是根據TeraSort規定的輸入資料的特點定製的,對普通資料不一定具有普遍適用性,比如Hadoop內建的TotalPartitioner就採用了更通用的二分查詢法來定位分割槽)

相關思考

由於Partitioner中將資料按Key值大小歸類到不同的分割槽中,而各個分割槽內部由Hadoop的框架進行了排序,所以最終得到的結果就是全域性排序的結果了

 

前面Sort.java在做全域性排序的時候也使用了類似的方法,不同的是取樣和分割槽定位的方式不同,實現的方式更加通用一些。

 

為了加快TeraSort資料輸出的速度,這個Job的data replica被設定為1

 

另外,http://blog.csdn.net/leafy1980/article/details/6633828  這裡對TeraSort做了更詳細的流程介紹

 

TestDFSIO : org.apache.hadoop.fs.TestDFSIO

功能目的  

測試 HDFS的讀寫速度

流程分析

使用Hadoop MapReduce框架的主要目的是通過多個Map Task模擬多路的併發讀寫。

 

TestDFSIO通過實現了自己的Mapper class用來讀寫資料,生成統計資訊,然後實現了自己的Reduce Class來收集並彙總各個Map Task的統計資訊,主要涉及到三個檔案 : AccumulatingReducer.java, IOMapperBase.java, TestDFSIO.java

 

程式的大致流程如下:

•       根據Map Task的數量將相應個數的Control控制檔案寫入HDFS,這些控制檔案僅包含一行內容:<資料檔名,資料檔案大小> 

•       啟動MapReduceJob,IOMapperBase Class中的Map方法將Control檔案作為輸入檔案,讀取內容,將資料檔名和大小作為引數傳遞給自定義的doIO函式,進行實際的資料讀寫工作。而後將資料大小和doIO執行的時間傳遞給自定義的collectStatus函式,進行統計資料的輸出工作 

•       doIO的實現:TestDFSIO過載並實現doIO函式,將指定大小的資料寫入HDFS檔案系統。

•       collectStatus的實現:TestDFSIO過載並實現collectStatus函式,將任務數量(1),以及資料大小,完成時間等相關資料作為Map Class的結果輸出

o  統計資料用不同的字首標識,例如 l: (stand for long), s: ( stand for string) etc.

 

•       執行唯一的一個Reduce任務,收集各個Map Class的統計資料,使用AccumulatingReducer進行彙總統計

•       最後當MapReduceJob完成以後,呼叫analyzeResult函式讀取最終的統計資料並輸出到控制檯和本地的Log檔案中

相關思考

可以看到在這個流程中,實際通過MR框架進行讀寫Shuffle的只是Control檔案,資料量非常小,所以MR框架本身的資料傳輸對測試的影響很小,可以忽略不計,測試結果完全取決於HDFS的讀寫效能。

相關文章