Mapreduce的Partition分区介绍

Hadoop学习

  • Mapreduce的Partition分区介绍
    • 1. Partition分区
    • 2. 自定义Partitioner步骤
    • 3. 自定义案例

Mapreduce的Partition分区介绍

1. Partition分区

在前面的Mapreduce流程中提到过在shuffle过程中有分区操作,分区决定着你开启的Reduce Task数量和最终的输出文件数量,在前面的案例中,我们能看到最终的输出文件都是只有一个,因为我们没有配置分区数量,他默认的数量是1个,所以最终的输出文件都是1个
那么当我们需要要求将统计结果按照条件输出到不同文件中(分区)。比如:将统计结果按照手机归属地不同省份输出到不同文件中(分区)的时候,就需要去配置分区的相应代码
默认的Partitioner分区:

public class HashPartitioner, V> extends Partitioner, V> {
    public HashPartitioner() {
    }

    public int getPartition(K key, V value, int numReduceTasks) {
        return (key.hashCode() & 2147483647) % numReduceTasks;
    }
}

这里的2147483647是2的31次方,是java int 类整数的最大值,也可以用Integer.MAX_VALUE表示,默认分区是根据key的hashCode对ReduceTasks个数取模得到的,用户没法控制哪个key存储到哪个分区。

2. 自定义Partitioner步骤

  1. 自定义类继承Partitioner, 重写getPartition()方法
public class XXXXX extends Partitioner,XXX> {
    @Override
    public int getPartition(XXX key, XXX value, int numPartitions) {
    //控制分区代码逻辑
    .... ....
    	return partition;
    }
}
  1. 在Driver驱动类中,设置自定义Partitioner
job.setPartitionerClass(XXXXX.class);
  1. 自定义Partition后,要根据自定义Partitioner的逻辑在Driver驱动类中设置相应数量的ReduceTask
job.setNumReduceTasks(XXX);
  1. 分区总结
    (1) 如果ReduceTask的数量 > getPautition的结果数,则会多产生几个空的输出文件part-000xx
    (2) 如果1 (3) 如果ReduceTask的数量=1, 则不管MapTask端输出多少个分区文件,最终结果都交给这一个ReduceTask,最终也就只会产牲一个结果文件part-00000
    (4) 分区号必须从零开始,逐一累加
    例:假设自定义分区数为5,则
    (1) job.setNumReduceTasks(1); 会正常运行,只不过会产生一个输出文件
    (2) job.setNumReduceTasks(2); 会报错
    (3) job.setNumR educeTasks(6); 大于5, 程序会正常运行,会产生空文件

3. 自定义案例

1.需求
将统计结果按照手机归属地不同省份输出到不同文件中(分区)
(1)输入数据
(2)期望输出数据
手机号136、137、138、139开头都分别放到一个独立的4个文件中,其他开头的放到一个文件中。
在自定义序列化案例的基础上,增加一个分区类
自定义序列化

package com.atguigu.mapreduce.flowsum;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner;

public class ProvincePartitioner extends Partitioner,FlowBean> {
    @Override
    public int getPartition(Text key, FlowBean value, int numPartitions) {
        //key是手机号
        //value是流量信息

        //获取手机号前三位
        String prePhoneNum = key.toString().substring(0,3);
        int partition = 4;
        if ("136".equals(prePhoneNum)){
            partition = 0;
        }else if("137".equals(prePhoneNum)){
            partition = 1;
        }else if("138".equals(prePhoneNum)){
            partition = 2;
        }else if("139".equals(prePhoneNum)){
            partition = 3;
        }
        return partition;
    }
}

在Driver驱动类中加入增加自定义数据分区设置和ReduceTask设置

job.setPartitionerClass(ProvincePartitioner.class);
job.setNumReduceTasks(5);

Driver类完整代码

package com.atguigu.mapreduce.flowsum;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

public class FlowsumDriver {

    public static void main(String[] args)
            throws IOException, ClassNotFoundException, InterruptedException {

        //1 获取job对象
        Configuration conf = new Configuration();
        Job job;
        job = Job.getInstance(conf);

        //2 设置jar路径
        job.setJarByClass(FlowsumDriver.class);

        //3 关联mapper和reducer
        job.setMapperClass(FlowCountMapper.class);
        job.setReducerClass(FlowCountReducer.class);

        //4 设置mapper输出的key和value
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(FlowBean.class);

        //5 设置最终输出的key和value
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(FlowBean.class);
        
        //增加自定义数据分区设置和ReduceTask设置
        job.setPartitionerClass(ProvincePartitioner.class);
        job.setNumReduceTasks(5);

        //6 设置输入输出路径
        FileInputFormat.setInputPaths(job,new Path("D:\\idea project\\MapReduce\\phone.txt"));
        FileOutputFormat.setOutputPath(job,new Path("D:\\idea project\\MapReduce\\output3"));

        //7 提交job
        boolean result = job.waitForCompletion(true);
        System.exit(result ? 0 : 1);
    }
}

查看结果
Mapreduce的Partition分区介绍_第1张图片
Mapreduce的Partition分区介绍_第2张图片

你可能感兴趣的:(hadoop)