MapReduce【自定义分区Partitioner】

简介: 实际开发中我们可能根据需求需要将MapReduce的运行结果生成多个不同的文件,比如上一个案例【MapReduce计算广州2022年每月最高温度】,我们需要将前半年和后半年的数据分开写到两个文件中。

实际开发中我们可能根据需求需要将MapReduce的运行结果生成多个不同的文件,比如上一个案例【MapReduce计算广州2022年每月最高温度】,我们需要将前半年和后半年的数据分开写到两个文件中。


默认分区

默认MapReduce只能写出一个文件:

image.png

因为我们在提交job的时候未设置reduceTask的个数,所以默认reduceTask的个数为1,结果也就只能输出一个文件,下面是数据写入文件时,默认调用的HashPartitioner类的getPartition方法:


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

因为reduceTask数量为1,任何数1取余结果为0,所以文件只有一个且文件名位 "part-r-00000"


自定义分区

1.继承Partitioner类

像HashPartitioner类一样继承Partitioner类


2.指定泛型

因为分区出现在map方法之后,所以两个泛型参数分别为map方法输出的key和value的类型


3.继承getPartition方法

继承后需要重写分区逻辑,也就是说如何根据输入的键或值来确定该行数据的分区。

设置自定义分区后,因为我们的输入格式是默认的TextInputFormat,所以每行数据都会通过getPartitioner方法来选择分区。

public class MyPartitioner extends Partitioner<Text, IntWritable> {
    @Override
    public int getPartition(Text text, IntWritable intWritable, int partitioner) {
        //text 是月份
        String month = text.toString();
        int month_num = Integer.parseInt(month);
        //注意:分区号必须从0开始!
        if (month_num<=6)   //前半年的数据放到分区0
            partitioner = 0;
        else                //后半年的数据放到分区1
            partitioner = 1;
        return partitioner;//返回分区号
    }
}

4.在job中设置分区

我们不仅要指定分区的类型还要指定reduceTask的数量,因为我们最后是根据分区的数量来分配给不同的reduceTask去执行。

这里我们只需要增加下面的语句即可,其余部分代码不需要改动。


//绑定自定义分区

       job.setPartitionerClass(MyPartitioner.class);

       //设置reduceTask个数

       job.setNumReduceTasks(2);

输出结果

image.png


注意点-reduceTask的数量

reduceTask数量 > 分区的数量

这种情况会造成CPU资源的浪费,因为会多开启 reduceTask ,它没有任务还空占大约1G内存。


1< reduceTask数量< 分区的数量

会抛出异常,因为有多余的分区剩下来没有reduceTask拉取处理。


reduceTask数量 =1

自定义分区失效,按照默认的分区规则(HashPartitioner的getPartitioner方法)执行,仍然只生成一个结果文件。


分区号必须从0开始

向下面这段代码一样,共划分了5个分区(0~4),结果会有5个结果文件产生。


if (条件1)   
     partitioner = 0;    //分区0
else if(条件2)                
     partitioner = 1;    //分区1
else if(条件3)                
     partitioner = 2;    //分区2
else if(条件4)                
     partitioner = 3;    //分区3
else                 
     partitioner = 4;    //分区4



相关文章
|
存储 分布式计算 关系型数据库
MapReduce【自定义OutputFormat】
MapReduce默认的输出格式为TextOutputFormat,它的父类是FileOutputFormat,即按行来写,且内容写到一个文本文件中去,但是并不能满足我们实际开发中的所有需求,所以就需要我们自定义OutPutFormat。
|
分布式计算
MapReduce【自定义InputFormat】
MapReduce在处理小文件时效率很低,但面对大量的小文件又不可避免,这个时候就需要相应的解决方案。
|
存储 分布式计算 Hadoop
Hadoop中的MapReduce框架原理、Shuffle机制、Partition分区、自定义Partitioner步骤、在Job驱动中,设置自定义Partitioner、Partition 分区案例
Hadoop中的MapReduce框架原理、Shuffle机制、Partition分区、自定义Partitioner步骤、在Job驱动中,设置自定义Partitioner、Partition 分区案例
Hadoop中的MapReduce框架原理、Shuffle机制、Partition分区、自定义Partitioner步骤、在Job驱动中,设置自定义Partitioner、Partition 分区案例
|
分布式计算
MapReduce自定义分区
MapReduce自定义分区
|
分布式计算 负载均衡 Hadoop
MapReduce 默认分区介绍
MapReduce 默认分区介绍
|
分布式计算
MapReduce编程例子之Combiner与Partitioner
MapReduce编程例子之Combiner与Partitioner
251 0
MapReduce编程例子之Combiner与Partitioner
|
分布式计算 数据挖掘
五十三、Mapreduce之自定义outputformat案例
五十三、Mapreduce之自定义outputformat案例
五十三、Mapreduce之自定义outputformat案例
|
分布式计算 自然语言处理 Java
MapReduce实现与自定义词典文件基于hanLP的中文分词详解
文本分类任务的第1步,就是对语料进行分词。在单机模式下,可以选择python jieba分词,使用起来较方便。但是如果希望在Hadoop集群上通过mapreduce程序来进行分词,则hanLP更加胜任。
2726 0
|
数据采集 分布式计算 搜索推荐
Hadoop学习---7、OutputFormat数据输出、MapReduce内核源码解析、Join应用、数据清洗、MapReduce开发总结(一)
Hadoop学习---7、OutputFormat数据输出、MapReduce内核源码解析、Join应用、数据清洗、MapReduce开发总结(一)
|
存储 分布式计算 Hadoop
Hadoop基础学习---6、MapReduce框架原理(一)
Hadoop基础学习---6、MapReduce框架原理(一)