自己对MapReduce中shuffle过程的理解

shuffle过程包括在Map和Reduce两端中。 

在Map端的shuffle过程是对Map的结果进行分区(partition)、排序(sort)和分割(spill),然后将属于同一个划分的输出合并在一起(merge)并写在硬盘上,同时按照不同的划分将结果发送给对应的Reduce(Map输出的划分与Reduce的对应关系由JobTracker确定)。Reduce端又会将各个Map送来的属于同一个划分的输出进行合并(merge),然后对merge的结果进行排序,最后交给Reduce处理。通俗的讲,就是对Map输出结果先进行分区(partition),如“aaa”经过Partitioner后返回0,也就是这对值应当交由第一个reducer来处理。接下来,需要将数据写入内存缓冲区中,缓冲区的作用是批量收集map结果,减少磁盘IO的影响。我们的key/value对以及Partition的结果都会被写入缓冲区。当然写入之前,key与value值都会被序列化成字节数组。这个内存缓冲区是有大小限制的,默认是100MB。当map task的输出结果很多时,需要在一定条件下将缓冲区中的数据临时写入磁盘,然后重新利用这块缓冲区。这个从内存往磁盘写数据的过程被称为Spill。Spill可以认为是一个包括Sort和Combiner(Combiner是可选的,用户如果定义就有)的过程。先进行sort可以把缓冲区中一段范围key的数据排在一起,(如果数据多的时候,多次刷新往内存缓冲区中写入的数据可能会有属于相同范围的key,也就是说,多个spill文件中可能会有统一范围的key,这就是需要下面Map端merge的原因),这里有点绕,具体的介绍可以看下面的详细过程,执行过sort之后,如果用户定义了combiner就会执行combine,然后执行merge操作,接着就是Reduce端。


详细过程如下:
Map端:

当Map输出内存缓冲区内容达到设定的阈值时,就要把缓冲区内容分割(spill)到磁盘中。但在分割的时候Map并不会阻止继续向缓冲区中写入结果,如果Map结果生成的速度快于写出速度,那么缓冲区会写满,这时Map任务必须等待,直到分割写出过程结束。其实Spill可以认为是一个包括Sort和Combiner(Combiner是可选的,用户如果定义就有)的过程。将缓冲区中的内容写出时会调用sortAndSpill函数,每被调用一次就会创建一个spill文件,然后按照key值对需要写出的数据进行sort,(如果用户作业配置了conbiner类,那么在写出过程中会先对sort的结果进行进一步的合并(combine),目的是为了让他Map的输出数据更加紧凑)。最后按照划分的顺序将所有要写出的结果写入这个溢写文件(spill文件)中。 每次溢写都会在磁盘上生成一个溢写文件,如果map的输出结果真的很大,就会有多次这样的溢写发生,磁盘上相应就会有多个溢写文件存在。当map task真正完成时,内存缓冲区中的数据也全部溢写到磁盘中形成一个溢写文件。最终磁盘中会至少有一个这样的溢写文件存在(如果map的输出结果很少,当map执行完成时,只会产生一个溢写文件),因为直接将每一个Map生成的众多spill文件交给Reduce处理不显示。所以在每个Map任务结束之后在Map的TaskTracker上还会执行合并操作(merge),这个操作的主要目的就是将Map生成的众多spill文件中的数据(此时每个spill中的数据已经经过sort过程,一段范围的key已经排在一起了)按照划分重新组织,针对指定的分区,从各个spill文件中拿出属于同一个分区的所有数据,然后将它们合并在一起,并写入一个已分区且已排序的Map输出文件中,(该过程的详细情况请参考mergeParts( )函数的代码)。待唯一的已分区且已排序的Map输出文件写入最后一条记录后,Map端的shuffle阶段就结束了。就进入了Reduce端的shuffle阶段。
Reduce端:

在Reduce端,shuffle阶段可以分为三个阶段:复制Map输出、排序合并(merge)和Reduce处理。
简单地说,reduce task在执行之前的工作就是不断地拉取当前job里每个map task的最终结果,然后对从不同地方拉取过来的数据不断地做merge,也最终形成一个文件作为reduce task的输入文件。
详细过程如下:
1. copy过程:简单地拉取数据。Reduce进程启动一些数据copy线程(Fetcher),通过HTTP方式请求map task所在的TaskTracker获取map task的输出文件。因为map task早已结束,这些文件就归TaskTracker管理在本地磁盘中。 
2.merge阶段。
这里的merge如map端的merge动作,只是数组中存放的是不同map端copy来的数值。Copy过来的数据会先放入内存缓冲区中。这里需要强调的是,merge有三种形式:1)内存到内存  2)内存到磁盘  3)磁盘到磁盘。默认情况下第一种形式不启用,让人比较困惑,是吧。当内存中的数据量到达一定阈值,就启动内存到磁盘的merge。与map 端类似,
这也是溢写的过程,这个过程中如果你设置有Combiner,也是会启用的,然后在磁盘中生成了众多的溢写文件。第二种merge方式一直在运行,直到没有map端的数据时才结束,然后启动第三种磁盘到磁盘的merge方式生成最终的那个文件。 
3. Reduce处理阶段
不断地merge后,最后会生成一个“最终文件”。为什么加引号?因为这个文件可能存在于磁盘上,也可能存在于内存中。对我们来说,当然希望它存放于内存中,直接作为Reducer的输入,但默认情况下,这个文件是存放于磁盘中的。当Reducer的输入文件已定,整个Shuffle才最终结束。然后就是Reducer执行,把结果放到HDFS上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值