Hadoop值Partition分区

分区操作

为什么要分区?

要求将统计结果按照条件输出到不同文件中(分区)。比如:将统计结果按
照手机归属地不同省份输出到不同文件中(分区)

默认 partition 分区

/**
	源码中:numReduceTasks如果等于1 不会走getPartition方法
	numReduceTasks:默认是1
*/
public class HashPartitioner<K, V> extends Partitioner<K, V> {
	public int getPartition(K key, V value, int numReduceTasks) {
		return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
	}
}

默认分区是根据 key 的 hashCode 对 reduceTasks 个数取模得到的。
用户没法控制哪个key 存储到哪个分区

自定义Partition

(1)自定义类继承 Partitioner,重写 getPartition()方法

/**
	该方法返回不同的partition的值,从而就控制了分区个数、前提是numReduceTasks不等于1
	KV:是Map的输出
*/
public class ProvincePartitioner extends Partitioner<Text, FlowBean> {
	@Override
	public int getPartition(Text key, FlowBean value, int numPartitions) {
		// 1 获取电话号码的前三位
		String preNum = key.toString().substring(0, 3);
		int partition = 4;
		// 2 判断是哪个省
		if ("136".equals(preNum)) {
			partition = 0;
		}else if ("137".equals(preNum)) {
			partition = 1;
		}else if ("138".equals(preNum)) {
			partition = 2;
		}else if ("139".equals(preNum)) {
			partition = 3;
		}
		return partition;
	}
}

(2)在Runner类中设置partition

job.setPartitionerClass(CustomPartitioner.class);

(3)自定义 partition 后,要根据自定义 partitioner 的逻辑设置相应数量的 reduce task

job.setNumReduceTasks(5);

(4)注意:

如果 reduceTask 的数量 > getPartition 的结果数,则会多产生几个空的输出文件part-r-000xx;

如果 1 < reduceTask的数量 < getPartition 的结果数,则有一部分分区数据无处安放,会Exception;

如果 reduceTask 的数量 = 1,则不管 mapTask 端输出多少个分区文件,最终结果都交给这一个 reduceTask,
最终也就只会产生一个结果文件 part-r-00000;

例如:假设自定义分区数为 5,则
(1)job.setNumReduceTasks(1);会正常运行,只不过会产生一个输出文件
(2)job.setNumReduceTasks(2);会报错
(3)job.setNumReduceTasks(6);大于 5,程序会正常运行,会产生空文件

本博客仅为博主学习总结,感谢各大网络平台的资料。蟹蟹!!

相关推荐
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:马嘣嘣 返回首页