图解shuffle

奇迹发生之处

Shuffle 是 MapReduce计算的核心过程,在各种教程和帖子中,往往被称为奇迹发生的地方。可惜总是语焉不详,令人困惑。今天尝试画了张大图,详细说明一下shuffle过程。

完整图如下:

可以看到,Shuffle过程从Mapper端开始,到Reducer端结束,有多个步骤。下面我尝试将图分解,逐步讲述。

我们都知道,Shuffle的意义在于把Mapper的输出结果交给不同的Reducer处理。

简单起见,假设我们的数据输出就是形如(k1,v1)的对。而最终分区就是按照k1, k2, k3 这样分成3个分区,我们图中所示的Reducer所需要处理的分就是k1 对应的分区。

Map侧

Spill

Map 的输出默认是输出到一个内存缓冲区中。这很容易理解,因为内存比磁盘快。但通常数据量大时,缓冲区很容易被用完。如图当内存缓冲区的使用达到一个阈值比如80%时,所谓的Spill即溢写启动。Spill的意义就在于把数据写入到磁盘,以使得后续的Map输出能够继续利用缓冲区。启动Spill时,已经写入的内容被锁定在内存中并持续写磁盘,同时原先的Map输出可以继续并行地往空闲内存写入。

<img style=”mergin:5px;”src=”/assets/img/Spill.png”>

Spill-Sort

Spill过程中先根据key对数据进行排序。排序很有意义,因为相同的key放在一起才方便输出文件的分区(不管是在内还是磁盘)。

Spill-Combine

Combine其实就是一种Reduce过程。按照你制定的Combiner进行处理,通常是把相同key的内容放在一起。

Merge

当你的Map输出很大,有多次溢写过程,就需要把多次的输出文件合并成一个大文件。

Reduce 侧

Reduce端需要按照分区原则,获得所有Map端输出的属于自己处理的分区文件。

Fetch

一旦有Map端任务完成时,Reducer端即可启动一个Fetcher线程去搜集对方输出的结果。注意只是收集结果,只有所依赖的所有Map端工作都完成了,才意味着Map结束,Reducer才可真正开始Reduce任务。

Fetcher只需要获取该Reducer所需要的分区。

Merge

同样,当Map输出多时,需要Merge过程。最终的结果也许是一个完整的文件(也许在内存,也许在磁盘,取决于量),也许不是(多个文件同时作为输入在reduce过程中进行最终合并)。

Shuffle的基本过程就是如此,很简单却很有效。本人水平有限,如文字和绘图有任何问题还请指出。



最后更新: 2015-05-18 20:03