Hadoop框架排序和分組的理解

MapReduce框架會確保每一個Reducer的輸入都是按Key進行排序的。一般,將排序以及Map的輸出傳輸到Reduce的過程稱爲混洗(shuffle)。每一個Map都包含一個環形的緩存,默認100MMap首先將輸出寫到緩存當中。當緩存的內容達到“閾值”時(閾值默認的大小是緩存的80%),一個後臺線程負責將結果寫到硬盤,這個過程稱爲“spill”。Spill過程中,Map仍可以向緩存寫入結果,如果緩存已經寫滿,那麼Map進行等待。

Spill的具體過程如下:首先,後臺線程根據Reducer的個數將輸出結果進行分組,每一個分組對應一個Reducer。其次,對於每一個分組後臺線程對輸出結果的Key進行排序。在排序過程中,如果有Combiner函數,則對排序結果進行Combiner函數進行調用。每一次spill都會在硬盤產生一個spill文件。因此,一個Map task有可能會產生多個spill文件,當Map寫出最後一個輸出時,會將所有的spill文件進行合併與排序,輸出最終的結果文件。在這個過程中Combiner函數仍然會被調用。從整個過程來看,Combiner函數的調用次數是不確定的。

Hadoop是如何進行排序的呢?根據筆者的理解,MapReduce的排序過程分爲兩個步驟,一個按照Key進行排序;一個是按照Key進行分組。這兩部分分別由SortComparatorGroupingComparator來完成。具體的配置如下面黑體所示:

job.setPartitionerClass(FirstPartitioner.class);

job.setSortComparatorClass(KeyComparator.class);

job.setGroupingComparatorClass(GroupComparator.class);

如果用戶想自定義排序方式,首先需要實現兩個Comparator並將其按照上面的格式進行配置。每一個Comparator需要繼承WritableComparator基類。如下所示:

public static class GroupComparator extends WritableComparator {

protected GroupComparator() {

super(IntPair.class, true);

}

@Override

public int compare(WritableComparable w1, WritableComparable w2) {

IntPair ip1 = (IntPair) w1;

IntPair ip2 = (IntPair) w2;

return IntPair.compare(ip1.getFirst(), ip2.getFirst());

}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章