1.分区(Partition) 和 ReduceTask

本文详细介绍了MapReduce中分区的概念及其实现方式,包括自定义分区的步骤、案例分析及源码解析,帮助读者理解如何控制数据如何分区及分几个区。

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,程序会正常运行,会产生空文件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值