1,map task默认通过TestInputStream来读取数据,一次读取一行返回key-value值,通过context.write写到OutPutCollector收集器中;
2,OutPutCollector将数据输出到环形缓冲区中,环形缓冲区的默认大小是100M,当缓冲区用到80%的时候,(也就是80M)会将环形缓冲区的中的数据溢出(spill)到文件;
3,在环形缓存区中的数据会进行分区和排序,MapReduce提供Partitioner接口,它的作用就是根据key或value及reduce的数量来决定当前的这对输出数据最终应该交由哪个reduce task处理。
4,溢出到文件的数据已经是分区好了的并且是有序的,这时候就要进行merge阶段,也就是将分区的数据进行合并排序;
5,再经过不断的merge的合并和排序之后,将数据交个reducer处理。
6,如果client设置过Combiner,那么现在就是使用Combiner的时候了。将有相同key的key/value对的value加起来,减少溢写到磁盘的数据量。Combiner会优化MapReduce的中间结果,所以它在整个模型中会多次使用。那哪些场景才能使用Combiner呢?从这里分析,Combiner的输出是Reducer的输入,Combiner绝不能改变最终的计算结果。Combiner只应该用于那种Reduce的输入key/value与输出key/value类型完全一致,且不影响最终结果的场景。比如累加,最大值等。Combiner的使用一定得慎重,如果用好,它对job执行效率有帮助,反之会影响reduce的最终结果。