mapreduce的map结束后,把数据重新组织,作为reduce阶段的输入,该过程称之为shuffle---洗牌。这个shuffle过程是整个mapreduce的心脏,如果理解了shuffle的过程,在必要的时候可以优化mapreduce程序的代码。
总结shuffle的主要功能:
1.完整地从map task端拉取数据到reduce 端;
2.在跨节点拉取数据时,尽可能地减少对带宽的不必要消耗;
3.减少磁盘IO对task执行的影响。
map函数在产生输出文件时,并不是简单地把数据直接写入磁盘,而是做了一系列复杂的动作。具体如下:
从上图可以看出,每个map有一个环形内存缓冲区,用来存储任务的输出。默认情况下缓冲区的大小是100MB,一旦缓冲区达到阈值,如写到了80%,一个后台线程就开始
把内容写到(spill)磁盘中。在写磁盘过程中,map输出继续被写到缓冲区,但是如果在此期间缓冲区被填满,map会阻塞直到写磁盘过程完成。
在写磁盘前,线程首先根据数据最终要送到的reducer把数据划分成相应的分区(partition),在每个分区中,后台线程按键进行内排序,如果有一个combiner,它会在排序后的输出上运行。
一旦内存缓冲区达到溢出写的阈值,就会新建一个溢出写文件,因此在map任务写完其最后一个输出记录之后,会有几个溢出写文件。在任务完成之前,溢出写文件被合并成一个已分区且已排序的输出文件。
如果已经指定combiner,并且溢出写次数至少为3时,则combiner就会在输出文件写到磁盘之前运行。combiner可以在输入上反复运行,但并不影响最终的结果。运行combiner的意义在于使map输出更紧凑,使得写到本地磁盘和传给reducer的数据更少。如果client设置过Combiner,那么现在就是使用Combiner的时候了。将有相同key的key/value对的value加起来,减少溢写到磁盘的数据量。Combiner会优化MapReduce的中间结果,所以它在整个模型中会多次使用。那哪些场景才能使用Combiner呢?从这里分析,Combiner的输出是Reducer的输入,Combiner绝不能改变最终的计算结果。所以从我的想法来看,Combiner只应该用于那种Reduce的输入key/value与输出key/value类型完全一致,且不影响最终结果的场景。比如累加,最大值等。Combiner的使用一定得慎重,如果用好,它对job执行效率有帮助,反之会影响reduce的最终结果。