Hadoop中的Partitioner淺析


轉自:http://blog.csdn.net/b1198103958/article/details/47169105

 

Hadoop里面的MapReduce編程模型,非常靈活,大部分環節我們都可以重寫它的API,來靈活定制我們自己的一些特殊需求。 

今天散仙要說的這個分區函數Partitioner,也是一樣如此,下面我們先來看下Partitioner的作用: 
對map端輸出的數據key作一個散列,使數據能夠均勻分布在各個reduce上進行后續操作,避免產生熱點區。 

大部分情況下,我們都會使用默認的分區函數,但有時我們又有一些,特殊的需求,而需要定制Partition來完成我們的業務,案例如下: 
對如下數據,按字符串的長度分區,長度為1的放在一個,2的一個,3的各一個。 

河南省;1 
河南;2 
中國;3 
中國人;4 
大;1 
小;3 
中;11 

這時候,我們使用默認的分區函數,就不行了,所以需要我們定制自己的Partition,首先分析下,我們需要3個分區輸出,所以在設置reduce的個數時,一定要設置為3,其次在partition里,進行分區時,要根據長度具體分區,而不是根據字符串的hash碼來分區。

總結

(Partition)分區出現的必要性,如何使用Hadoop產生一個全局排序的文件?最簡單的方法就是使用一個分區,但是該方法在處理大型文件時效率極低,因為一台機器必須處理所有輸出文件,從而完全喪失了MapReduce所提供的並行架構的優勢。事實上我們可以這樣做,首先創建一系列排好序的文件;其次,串聯這些文件(類似於歸並排序);最后得到一個全局有序的文件。主要的思路是使用一個partitioner來描述全局排序的輸出。比方說我們有1000個1-10000的數據,跑10個ruduce任務, 如果我們運行進行partition的時候,能夠將在1-1000中數據的分配到第一個reduce中,1001-2000的數據分配到第二個reduce中,以此類推。即第n個reduce所分配到的數據全部大於第n-1個reduce中的數據。這樣,每個reduce出來之后都是有序的了,我們只要cat所有的輸出文件,變成一個大的文件,就都是有序的了 


基本思路就是這樣,但是現在有一個問題,就是數據的區間如何划分,在數據量大,還有我們並不清楚數據分布的情況下。一個比較簡單的方法就是采樣,假如有一億的數據,我們可以對數據進行采樣,如取10000個數據采樣,然后對采樣數據分區間。在Hadoop中,patition我們可以用TotalOrderPartitioner替換默認的分區。然后將采樣的結果傳給他,就可以實現我們想要的分區。在采樣時,我們可以使用hadoop的幾種采樣工具,RandomSampler,InputSampler,IntervalSampler。 


       這樣,我們就可以對利用分布式文件系統進行大數據量的排序了,我們也可以重寫Partitioner類中的compare函數,來定義比較的規則,從而可以實現字符串或其他非數字類型的排序,也可以實現二次排序乃至多次排序。

combine、partition和shuffle的區別:

combine和partition都是函數,中間的步驟應該只有shuffle!


combine分為map端和reduce端,作用是把同一個key的鍵值對合並在一起,可以自定義的。
combine函數把一個map函數產生的<key,value>對(多個key,value)合並成一個新的<key2,value2>.將新的<key2,value2>作為輸入到reduce函數中
這個value2亦可稱之為values,因為有多個。這個合並的目的是為了減少網絡傳輸。

partition是分割map每個節點的結果,按照key分別映射給不同的reduce,也是可以自定義的。這里其實可以理解歸類。
我們對於錯綜復雜的數據歸類。比如在動物園里有牛羊雞鴨鵝,他們都是混在一起的,但是到了晚上他們就各自牛回牛棚,羊回羊圈,雞回雞窩。partition的作用就是把這些數據歸類。只不過在寫程序的時候,mapreduce使用哈希HashPartitioner幫我們歸類了。這個我們也可以自定義。

shuffle就是map和reduce之間的過程,包含了兩端的combine和partition。

Map的結果,會通過partition分發到Reducer上,Reducer做完Reduce操作后,通過OutputFormat,進行輸出
shuffle階段的主要函數是fetchOutputs(),這個函數的功能就是將map階段的輸出,copy到reduce 節點本地。

補充:

Map的結果,會通過partition分發到Reducer上,Reducer做完Reduce操作后,通過OutputFormat,進行輸出,下面我們就來分析參與這個過程的類。
Mapper的結果,可能送到Combiner做合並,Combiner在系統中並沒有自己的基類,而是用Reducer作為Combiner的基類,他們對外的功能是一樣的,只是使用的位置和使用時的上下文不太一樣而已。Mapper最終處理的鍵值對<key, value>,是需要送到Reducer去合並的,合並的時候,有相同key的鍵/值對會送到同一個Reducer那。哪個key到哪個Reducer的分配過程,是由Partitioner規定的。它只有一個方法,
getPartition(Text key, Text value, int numPartitions)  
輸入是Map的結果對<key, value>和Reducer的數目,輸出則是分配的Reducer(整數編號)。就是指定Mappr輸出的鍵值對到哪一個reducer上去。系統缺省的Partitioner是HashPartitioner,它以key的Hash值對Reducer的數目取模,得到對應的Reducer。這樣保證如果有相同的key值,肯定被分配到同一個reducre上。如果有N個reducer,編號就為0,1,2,3……(N-1)。
Reducer是所有用戶定制Reducer類的基類,和Mapper類似,它也有setup,reduce,cleanup和run方法,其中setup和cleanup含義和Mapper相同,reduce是真正合並Mapper結果的地方,它的輸入是key和這個key對應的所有value的一個迭代器,同時還包括Reducer的上下文。系統中定義了兩個非常簡單的Reducer,IntSumReducer和LongSumReducer,分別用於對整形/長整型的value求和。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM