mr partitioner

Map Partitioner Reduce


默认

 //partitioner只是一个abstract class,其实现类
    //hashpartitioner 根据hash算法模取余reducenum得到一致性分区,和mysql分库一致性hash算法
    /*
    public class HashPartitioner implements Partitioner {
    public HashPartitioner() {
    }

    public void configure(JobConf job) {
    }

    public int getPartition(K2 key, V2 value, int numReduceTasks) {
        return (key.hashCode() & 2147483647) % numReduceTasks;
    }
}




maptask执行后,分区采用hashPartitioner为默认方法分区,其实现了partitioner,通过getPartitioner方法 key.hashcode%numReduceTask,返回分区号

保证了同key的到同一个分区里面,因为同一个key的hashcode是相同的

但有时需要重写partitioner来实现业务的需求

如 将相同省份的手机号放到相同的文件中,

分析:相同省份到放到相同文件中,因为partitioner后就是reduce则同等数量的reduce,同等的分区,

实现partitioner方法,


package com.qq.bd;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner;

import java.util.HashMap;

//参数为map的输出结果
public class FlowPartitioner extends Partitioner<Text, FlowBean> {
//    partitioner每一个kv对调用一次partitioner,很慢
//    所以提前把逻辑加载到内存中

    public static HashMap<String, Integer> provinceDict = new HashMap<String, Integer>();

    static {
        provinceDict.put("136", 0);
        provinceDict.put("137", 1);
        provinceDict.put("138", 2);
        provinceDict.put("139", 3);

    }

    @Override
    public int getPartition(Text text, FlowBean flowBean, int i) {
//根据textkey返回不同的分区号

        String prefix = text.toString().substring(0, 3);
        Integer provinceId = provinceDict.get(prefix);
        return provinceId == null ? 4 : provinceId;
//        还需要在main方法中添加
        /*
        job.setpartitioner()来覆盖原来的默认partitioner
        还有分区数量也要设定一下,partitioner数量和reduce数量一致
        如果reduce数量为一,则全部结果都会放到一个文件中,这也是默认值
        如果reduce数量少于partitioner数量,则会报错因为狼多肉少会打起来
        如果reduce数量大于partitioner数量,则多的reduce中会是u空文件
         job.setNumReduceTasks(5);
         */
    }
}


你可能感兴趣的:(hadoop)