Hadoop 学习笔记(十四)Partition 分区

1、Shuffle机制定义

Map方法之后,Reduce方法之前的数据处理过程称之为Shuffle;

 2、Partition 

2.1、问题引入

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

2.2、默认分区

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存储到哪个分区。

2.3、自定义Partitioner步骤

 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);

2.4、分区总结 

  • 如果ReduceTask的数量> getPartition的结果数,则会多产生几个空的输出文件part-r-000xx;
  • 如果1<ReduceTask的数量<getPartition的结果数,则有一部分分区数据无处安放,会Exception;
  • 如果ReduceTask的数量=1,则不管MapTask端输出多少个分区文件,最终结果都交给这一个ReduceTask,最终也就只会产生一个结果文件 part-r-00000;
  • 分区号必须从零开始,逐一累加;

2.5、分区案例

需求说明:将统计结果按照手机归属地不同省份输出到不同文件中(分区)

输入数据:

1     13736230513    192.196.100.1    www.qq,tv.com    2481    24681    200
2     13846544121    192.196.100.2            264    0    200
3     13956435636    192.196.100.3            132    1512    200
4     13966251146    192.168.100.1            240    0    404
5     18271575951    192.168.100.2    www.qq,tv.com    1527    2106    200
6     19884188413    192.168.100.3    www.qq,tv.com    4116    1432    200
7     13590439668    192.168.100.4            1116    954    200
8     15910133277    192.168.100.5    www.hao123.com    3156    2936    200
9     13729199489    192.168.100.6            240    0    200
10     13630577991    192.168.100.7    www.shouhu.com    6960    690    200
11     15043685818    192.168.100.8    www.baidu.com    3659    3538    200
12     15959002129    192.168.100.9    www.qq,tv.com    1938    180    500
13     13560439638    192.168.100.10            918    4938    200
14     13470253144    192.168.100.11            180    180    200
15     13682846555    192.168.100.12    www.qq.com    1938    2910    200
16     13992314666    192.168.100.13    www.gaga.com    3008    3720    200
17     13509468723    192.168.100.14    www.qinghua.com    7335    110349    404
18     18390173782    192.168.100.15    www.sogou.com    9531    2412    200
19     13975057813    192.168.100.16    www.baidu.com    11058    48243    200
20     13768778790    192.168.100.17            120    120    200
21     13568436656    192.168.100.18    www.alibaba.com    2481    24681    200
22     13568436656    192.168.100.19            1116    954    200

 2.6、分区代码实现

在原有序列化案例基础上进行实现分区输出;

编写分区代码:

public class ProvPartition extends Partitioner<Text, FlowBean> {

    @Override
    public int getPartition(Text key, FlowBean value, int numPartitions) {
        // key 手机号,value 流量信息
        // 获取手机号前三位
        String deviveNumber = key.toString().substring(0, 3);
        int part = 4;
        if ("136".equals(deviveNumber)) {
            part = 0;
        } else if ("137".equals(deviveNumber)) {
            part = 1;
        } else if ("138".equals(deviveNumber)) {
            part = 2;
        } else if ("139".equals(deviveNumber)) {
            part = 3;
        }
        return part;
    }

}

Driver 关联分区类:

// 设置分区关联
        job.setPartitionerClass(ProvPartition.class);

注意:当使用分区对结果进行处理时,需要设置 ReduceTasks 数量,

job.setNumReduceTasks(5);

当数量设设置为 1 时,及时设置了分区,也不会进行分区操作,当分区数=ReduceTask 数量时,进行分区操作;

原文地址:https://www.cnblogs.com/wdh01/p/13834201.html