MapReduce之Shuffle机制-自定义分区-05

Mapreduce确保每个reducer的输入都是按key键排序的。系统执行排序的过程(即将map输出作为输入传给reducer)称为shuffle。map之后reduce之前都是suffer.

就是下面这个图从mapper程序出来到缓冲区,缓冲区到分区的过程中对key进行排序,分区是在内存中操作,然后落盘到硬盘上,然后传给reduce的过程中还要进行合并,这个过程称为shuffle.

默认是使用key的hash进行分区的.

实际操作

MapReduce序列化即案例演示-02

https://blog.csdn.net/kxj19980524/article/details/89282996

按手机号码前三位进行分区,135,136,137,138各一分区,剩下的为一分区.

在案例2上进行操作,写一个自定义分区类.

package com.buba.mapreduce.flow;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner;
//key和value的类型为mapper的输出key,value的类型
public class FlowPartitioner extends Partitioner<Text,FlowBean> {

    @Override
    public int getPartition(Text key, FlowBean flowBean, int i) {
        //1.需求:根据电话号码的前三位是几来分区

        //拿到电话号码的前三位
        String phoneNum = key.toString().substring(0, 3);

       //总共定义了五个分区

        //剩下的为4分区
        int partition = 4;

        if("135".equals(phoneNum)){ //如果开头是135那么就把这个key放0分区.
            partition = 0;
        }else if("136".equals(phoneNum)){//如果开头是136那么就把这个key放1分区.
            partition = 1;
        }else if("137".equals(phoneNum)){//如果开头是137那么就把这个key放2分区.
            partition = 2;
        }else if("138".equals(phoneNum)){//如果开头是138那么就把这个key放3分区.
            partition = 3;
        }
        return partition;
    }
}

 //设置分区
        job.setPartitionerClass(FlowPartitioner.class);

        //设置reducetask个数也就是得和FlowPartitioner里设置的分区个数一致
        job.setNumReduceTasks(5);

执行完后就按自定义的生成五个分区了 

注意:

如果reduceTask的数量> getPartition的结果数,则会多产生几个空的输出文件part-r-000xx;

如果1<reduceTask的数量<getPartition的结果数,则有一部分分区数据无处安放,会Exception;

如果reduceTask的数量=1,则不管mapTask端输出多少个分区文件,最终结果都交给这一个reduceTask,最终也就只会产生一个结果文件 part-r-00000;

       例如:假设自定义分区数为5,则

(1)job.setNumReduceTasks(1);会正常运行,只不过会产生一个输出文件

(2)job.setNumReduceTasks(2);会报错

(3)job.setNumReduceTasks(6);大于5,程序会正常运行,会产生空文件

 

MapReduce概述和编写简单案例-01

https://blog.csdn.net/kxj19980524/article/details/89281292

wordcount案例上按单词首字母的ASCLL码的基偶进行分区

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

public class WordCountPartitioner extends Partitioner<Text, IntWritable>{

	// hadoop 
	@Override
	public int getPartition(Text key, IntWritable value, int numPartitions) {
		// 需求:按照单词首字母的ASCII的奇偶分区
		String line = key.toString();
		
		// 1 截取首字母
		String firword = line.substring(0, 1);
		
		// 2 转换成ASCII
		char[] charArray = firword.toCharArray();
		
		int result = charArray[0];
		
		// 3 按照奇偶分区
		if (result % 2 ==0 ) {
			return 0;
		}else {
			return 1;
		}
	}
}

然后把driver里的 setNumReduceTasks(2);设置为2就可以了

猜你喜欢

转载自blog.csdn.net/kxj19980524/article/details/89301024