Map Partitioner Reduce
默认
//partitioner只是一个abstract class,其实现类 //hashpartitioner 根据hash算法模取余reducenum得到一致性分区,和mysql分库一致性hash算法 /* public class HashPartitioner<K2, V2> implements Partitioner<K2, V2> { 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) { //根据text即key返回不同的分区号 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); */ } }