MapTask,ReduceTask工作机制(包括shuffle阶段),OutCollector中Partitioner源码分析

MapReduce大致流程:
inputformat -> Mapper -> Shuffle(各种排序,分区排序,归并排序) -> Reducer -> outputformat

shuffle过程位于map()方法之后,reduce()方法之前。

MapTask的工作机制(包括shuffle过程,包括ReduceTask):

​ 【MapTask通过InputFormat获得RecordReader,输出keyValue,再交给mapper中用户定义的Map()方法中处理,当数据处理完成后,一般会调用OutputCollector.collect()输出结果。在这个方法内部,它会调用Partitioner对key/value数据进行分区;然后就开始shuffle过程,【ouputCollector将分区后的数据写入环形缓冲区中,环形缓冲区底层是一个100M大小的数组,可以两边写数据,右边写keyvalue数据,左边写元数据,元数据包括:index,partition,keystart , valstart。当数据达到环形缓冲区的80%时候,会进行分区排序(快排,排序的过程中是对索引进行排序),如果设置了combiner会进行分区内汇总。再溢写文件到本地磁盘,在溢写的过程中,缓冲区中的那20%也会反向向两边写数据。溢写的文件中是分区且有序的,而且可能有多个,这些文件会归并排序到一个大文件中,如果设置了combiner还会进行分区汇总。】,等到maptask任务完成后,【就会启动相应数量的reducetask(具体多少需要进行实验,设置reducetask的数量,调查相应的执行效率),reducetask会根据分区号主动去抓取不同的maptask机器上的相同分区的结果文件到内存中,如果内存不够,会溢写磁盘中,然后reducetask再将这些文件归并排序成一个大文件,交给Reducer()方法。到这里Shuffle过程就结束了。】

后面就到了reducetask的逻辑运算过程,也就是调用用户自定义的reduce方法,对每组key value进行统计处理。

(这里的value是一个集合,什么样的集合?看需求!如果是单词统计案例,value就是一个或多个1组成的集合,如果是统计手机的上下行总流量,那就是一个或多个flowbean类型的对象集合。)

Maptask工作机制流程图:在这里插入图片描述

Shuffle机制

在这里插入图片描述

ReduceTask工作机制(包括shuffle过程):

在这里插入图片描述

reducetask会根据分区号主动去抓取不同的maptask机器上的相同分区的结果文件,然后每个reducetask再将这些文件归并排序成一个大文件,到这里***Shuffle过程***就结束了。

注意事项
1. ReduceTask=0,表示没有Reduce阶段,输出文件个数和Map个数一致。
2. ReduceTask默认值就是1,所以输出文件个数为一个。
3. 如果数据分布不均匀,就有可能在Reduce阶段产生数据倾斜。
4. ReduceTask数量并不是任意设置,还要考虑业务逻辑需求,有些情况下,需要计算全局汇总结果,就只能有1个ReduceTask。
5. 具体多少个ReduceTask,需要根据集群性能而定。
6. 如果分区数不是1,但是ReduceTask为1,是否执行分区过程。答案是:不执行分区过程。因为在MapTask的源码中,执行分区的前提是先判断ReduceNum个数是否大于1。不大于1肯定不执行。
OutCollector中Partitioner源码分析
Job.setNumReduceTasks(1)  结果会有一个分区文件part-r-00000,不会走到
Job.setNumReduceTasks(0) 不会到shuffle阶段,直接执行完Map阶段就结束了。最后输出的文件为part-m-00000

// get an output object
if (job.getNumReduceTasks() == 0) {
//如果不设置走默认的
  output = 
    new NewDirectOutputCollector(taskContext, job, umbilical, reporter);
} else {
  output = new NewOutputCollector(taskContext, job, umbilical, reporter);
}
NewOutputCollector(org.apache.hadoop.mapreduce.JobContext jobContext,
                   JobConf job,
                   TaskUmbilicalProtocol umbilical,
                   TaskReporter reporter
                   ) throws IOException, ClassNotFoundException {
  collector = createSortingCollector(job, reporter);
  partitions = jobContext.getNumReduceTasks(); //job对象中获取ReduceTasks的数量
  if (partitions > 1) {
// 如果设置的ReduceTask数据大于1,就会走我们自定义的分区类
    partitioner = (org.apache.hadoop.mapreduce.Partitioner<K,V>)
      ReflectionUtils.newInstance(jobContext.getPartitionerClass(), job);
  } else {
// 如果设置为1时,partitioner分区类就是一个匿名内部类对象,就只有一个分区0000
    partitioner = new org.apache.hadoop.mapreduce.Partitioner<K,V>() {
      @Override
      public int getPartition(K key, V value, int numPartitions) {
        return partitions - 1;
      }
    };
  }
}

	//Partitioner会对key/value数据进行分区
    @Override
    public void write(K key, V value) throws IOException, InterruptedException {
      collector.collect(key, value,
                        partitioner.getPartition(key, value, partitions));
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值