Hadoop排序
Hadoop排序,從大的範圍來說有兩種排序,一種是按照key排序,一種是按照value排序。如果按照value排序,只需在map函式中將key和value對調,然後在reduce函式中在對調回去。從小範圍來說排序又分成部分排序,全域性排序,輔助排序,二次排序等。本文介紹如何在Hadoop中實現全域性排序。
全域性排序,就是說在一個MapReduce程式產生的輸出檔案中,所有的結果都是按照某個策略進行排序的,例如降序還是升序。MapReduce只能保證一個分割槽內的資料是key有序的,一個分割槽對應一個reduce,因此只有一個reduce就保證了資料全域性有序,但是這樣又不能用到Hadoop叢集的優勢。
對於多個reduce如何保證資料的全域性排序呢?通常的做法是按照key值分割槽,通過MapReduce的預設分割槽函式HashPartition將不同範圍的key傳送到不同的reduce處理,例如一個檔案中有key值從1到10000的資料,我們使用兩個分割槽,將1到5000的key傳送到partition1,然後由reduce1處理,5001到10000的key發動到partition2然後由reduce2處理,reduce1中的key是按照1到5000的升序排序,reduce2中的key是按照5001到10000的升序排序,這樣就保證了整個MapReduce程式的全域性排序。但是這樣做有兩個缺點:
1、當資料量大時會出現OOM。
2、會出現資料傾斜。
Hadoop提供TotalOrderPartitioner類用於實現全域性排序的功能,並且解決了OOM和資料傾斜的問題。
TotalOrderPartitioner類提供了資料取樣器,對key值進行部分取樣,然後按照取樣結果尋找key值的最佳分割點,將key值均勻的分配到不同的分割槽中。
TotalOrderPartitioner 類提供了三個取樣器,分別是:
- SplitSampler 分片取樣器,從資料分片中取樣資料,該取樣器不適合已經排好序的資料
- RandomSampler隨機取樣器,按照設定好的取樣率從一個數據集中取樣
- IntervalSampler間隔取樣機,以固定的間隔從分片中取樣資料,對於已經排好序的資料效果非常好。
三個取樣器都實現了K[] getSample(InputFormat<K,V> inf, Job job)方法,該方法返回的是K[]陣列,陣列中存放的是根據取樣結果返回的key值,即分隔點,MapRdeuce就是根據K[]陣列的長度N生成N-1個分割槽partition數量,然後按照分割點的範圍將對應的資料傳送到對應的分割槽中。