MapReduce框架Partitioner分割槽方法

Thinkgamer_gyt發表於2015-08-07

前言:對於二次排序相信大家也是似懂非懂,我也是一樣,對其中的很多方法都不理解誒,所有隻有暫時放在一邊,當你接觸到其他的函式,你知道的越多時你對二次排序的理解也就更深入了,同時建議大家對wordcount的流程好好分析一下,要真正的知道每一步都是幹什麼的。

1.Partitioner分割槽類的作用是什麼?
2.getPartition()三個引數分別是什麼?
3.numReduceTasks指的是設定的Reducer任務數量,預設值是是多少?
擴充套件:
如果不同型別的資料被分配到了同一個分割槽,輸出的資料是否還是有序的?

在進行MapReduce計算時,有時候需要把最終的輸出資料分到不同的檔案中,比如按照省份劃分的話,需要把同一省份的資料放到一個檔案中;按照性別劃分的話,需要把同一性別的資料放到一個檔案中。我們知道最終的輸出資料是來自於Reducer任務。那麼,如果要得到多個檔案,意味著有同樣數量的Reducer任務在執行。Reducer任務的資料來自於Mapper任務,也就說Mapper任務要劃分資料,對於不同的資料分配給不同的Reducer任務執行。Mapper任務劃分資料的過程就稱作Partition。負責實現劃分資料的類稱作Partitioner。

Partitoner類的原始碼如下:

package org.apache.hadoop.mapreduce.lib.partition;

import org.apache.hadoop.mapreduce.Partitioner;

/** Partition keys by their {@link Object#hashCode()}. */
public class HashPartitioner<K, V> extends Partitioner<K, V> {

  /** Use {@link Object#hashCode()} to partition. */
  public int getPartition(K key, V value,
                          int numReduceTasks) {
    //預設使用key的hash值與上int的最大值,避免出現資料溢位 的情況
    return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
  }

}
HashPartitioner是處理Mapper任務輸出的,getPartition()方法有三個形參,原始碼中key、value分別指的是Mapper任務的輸出,numReduceTasks指的是設定的Reducer任務數量,預設值是1。那麼任何整數與1相除的餘數肯定是0。也就是說getPartition(…)方法的返回值總是0。也就是Mapper任務的輸出總是送給一個Reducer任務,最終只能輸出到一個檔案中。
據此分析,如果想要最終輸出到多個檔案中,在Mapper任務中對資料應該劃分到多個區中。那麼,我們只需要按照一定的規則讓getPartition(…)方法的返回值是0,1,2,3…即可。
大部分情況下,我們都會使用預設的分割槽函式,但有時我們又有一些,特殊的需求,而需要定製Partition來完成我們的業務,案例如下:
對如下資料,按字串的長度分割槽,長度為1的放在一個,2的一個,3的各一個。

河南省;1
河南;2
中國;3
中國人;4
大;1
小;3
中;11
這時候,我們使用預設的分割槽函式,就不行了,所以需要我們定製自己的Partition,首先分析下,我們需要3個分割槽輸出,所以在設定reduce的個數時,一定要設定為3,其次在partition裡,進行分割槽時,要根據長度具體分割槽,而不是根據字串的hash碼來分割槽。核心程式碼如下:

   public static class PPartition extends Partitioner<Text, Text>{ 
    @Override
    public int getPartition(Text arg0, Text arg1, int arg2) {
       /**
        * 自定義分割槽,實現長度不同的字串,分到不同的reduce裡面
        * 
        * 現在只有3個長度的字串,所以可以把reduce的個數設定為3
        * 有幾個分割槽,就設定為幾
        * */
      
      String key=arg0.toString();
      if(key.length()==1){
        return 1%arg2;
      }else if(key.length()==2){
        return 2%arg2;
      }else if(key.length()==3){
        return 3%arg2;
      }
     return  0;
    }      
   }

在執行Mapreduce程式時,只需在主函式里加入如下兩行程式碼即可:

job.setPartitionerClass(PPartition.class);
job.setNumReduceTasks(3);//設定為3


相關文章