Hadoop 二次排序: 三個設置以及作用

爲什麼要有二次排序?

Hadoop框架本身提供對Key的排序,但是正如我們在SQL中的雙重排序要求一樣,有時候我們會需要對key相同值按另一個字段排序的需求,這就使得我們必須要利用Hadoop的機制來間接實施二次排序。

 

步驟:

1、定義一個複合鍵(因爲MapReduce只能對Key進行排序)

2、設置新的 comparator,用於對 Key 進行排序(等於Java中自定義Sort方法)

3、設置partitioner, 用於將數據對放在同一個reducer上(決定一個鍵值對去向哪裏)
 

 

疑問:

在原本沒有複合鍵的情況下,框架通過對key進行排序的方式將key相同的部分組合(group)在一起,那對於複合鍵來說,既然我已經分別定義了排序和分組,爲什麼還要指定分區(Partitioner)呢?

原理參考以下(來自於 https://www.cnblogs.com/DreamDrive/p/7693452.html):

原理:

map階段:

使用job.setInputFormatClass定義的InputFormat將輸入的數據集分割成小數據塊splites,同時InputFormat提供一個RecordReder的實現。

本例子中使用的是TextInputFormat,他提供的RecordReder會將文本的一行的行號作爲key,這一行的文本作爲value。這就是自定義Map的輸入是<LongWritable, Text>的原因。

然後調用自定義Map的map方法,將一個個<LongWritable, Text>對輸入給Map的map方法。注意輸出應該符合自定義Map中定義的輸出<IntPair, IntWritable>。最終是生成一個List<IntPair, IntWritable>。

在map階段的最後,會先調用job.setPartitionerClass對這個List進行分區,每個分區映射到一個reducer。每個分區內又調用job.setSortComparatorClass設置的key比較函數類排序。

可以看到,這本身就是一個二次排序。如果沒有通過job.setSortComparatorClass設置key比較函數類,則使用key的實現的compareTo方法。

 

reduce階段:

reducer接收到所有映射到這個reducer的map輸出後,也是會調用job.setSortComparatorClass設置的key比較函數類對所有數據對排序。

然後開始構造一個key對應的value迭代器。這時就要用到分組,使用jobjob.setGroupingComparatorClass設置的分組函數類。

只要這個比較器比較的兩個key相同,他們就屬於同一個組,它們的value放在一個value迭代器,而這個迭代器的key使用屬於同一個組的所有key的第一個key。

最後就是進入Reducer的reduce方法,reduce方法的輸入是所有的(key和它的value迭代器)。同樣注意輸入與輸出的類型必須與自定義的Reducer中聲明的一致。  

 

我的理解是,MapReduce是先將鍵值對分區到各個Reducer,再由各個Reducer進行內部排序,再分組,所以在一開始的時候就需要設置好Partioner。

否則自然鍵(我們希望用於分組的鍵)相同而複合鍵不同的鍵值對可能不在同一個Reducer上!那麼即使在多個Reducer上分別進行排序和分組及寫入記錄,我們最後得到的結果並不是全局有序的(多個Reducer產生多個文件)。

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