1.MapReduce之分区(Partition)
分区的意思就是,按照条件输出到不同文件中(分区)。比如统计居民身份信息,每10年设置一个分区。这时我们就需要,写一个类去继承我们 partitioner<xxxx, xxxx> 类, 这个类中有两个泛型参数。这里需要理解的是,这两个参数是来自我们自定义 Map 方法的输出。
2.自定义Partition步骤
自定义分区,也就是说我们可以规定: 1. 数据如何分区 2.分几个区
(1)自定义类继承Partitioner,重写getPartition()方法
public class CustomPartitioner extends Partitioner<Text, FlowBean> {
@Override
public int getPartition(Text key, FlowBean value, int numPartitions) {
// 控制分区代码逻辑
… …
return partition;
}
}
(2)在Job驱动中,设置自定义Partitioner
job.setPartitionerClass(CustomPartitioner.class);
(3)自定义Partition后,要根据自定义Partitioner的逻辑设置相应数量的ReduceTask
job.setNumReduceTasks(5);
代码实现:比如一组数据,我们已经取出了所有想要的数据,这时候我们想给给这些数分区。
3.自定义分区实列
1. 写一个类继承 Partitioner 类,(别忘记泛型参数)
2. 重写 getPartition() 方法
3. 分区类写完以后,我们要再驱动类里(Driver.class) 设置一下
job.setPartitionerClass(CustomPartitioner.class);
4. 我们需要设置NumReduceTest的数量和分区数一致()
//对手机号码前三位,进行分区
package sortAllPhone;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner;
/**
* @author tccstart
* @create 2020-08-11 18:24
* 这里的泛型键值对,是来自己Map输出
*/
public class partitionPhone2 extends Partitioner<phoneFlowBean, Text> {
@Override
public int getPartition(phoneFlowBean phoneFlowBean, Text text, int i) {
String phone = text.toString();
String prePhone = phone.substring(0, 3);
int partition;
if("136".equals(prePhone)){
partition = 0;
}else if("137".equals(prePhone)){
partition = 1;
}else if("138".equals(prePhone)){
partition = 2;
}else if("139".equals(prePhone)){
partition = 3;
}else {
partition = 4;
}
return partition;
}
}
4.分区源码
默认分区是根据key的hashCode对ReduceTasks个数取模得到的。用户没法控制哪个key存储到哪个分区。

从源码我们我们看以看到最后一行:
//从源码我们我们看以看到最后一行我们可以看到, 这是hadoop默认 规划分区设置
return (key.hashCode() & Integer.MAX_Value) % numReduceTasks
//key.hashCode() & Integer.MAX_Value 这是一个去高位操作,如果这个key的哈希值大于二进制整数型最大值(111111...),大于部分将会被去除,然后对ReduceTask取模。
//试想一下, 我们现在只有一个ReduceTask, 那么所有的数对 1 取模都是0,所以只有一个分区。
5.分区总结
(1)如果ReduceTask的数量> getPartition的结果数,则会多产生几个空的输出文件part-r-000xx;
(2)如果1<ReduceTask的数量<getPartition的结果数,则有一部分分区数据无处安放,会Exception;
(3)如果ReduceTask的数量=1,则不管MapTask端输出多少个分区文件,最终结果都交给这一个ReduceTask,最终也就只会产生一个结果文件 part-r-00000;
(4)分区号必须从零开始,逐一累加。
5.案例分析
例如:假设自定义分区数为5,则
(1)job.setNumReduceTasks(1); 会正常运行,只不过会产生一个输出文件
(2)job.setNumReduceTasks(2); 会报错
5.案例分析
例如:假设自定义分区数为5,则
(1)job.setNumReduceTasks(1); 会正常运行,只不过会产生一个输出文件
(2)job.setNumReduceTasks(2); 会报错
(3)job.setNumReduceTasks(6); 大于5,程序会正常运行,会产生空文件
本文详细介绍了MapReduce中分区的概念及其实现方式,包括自定义分区的步骤、案例分析及源码解析,帮助读者理解如何控制数据如何分区及分几个区。
1208

被折叠的 条评论
为什么被折叠?



