MapReduce的Shuffle过程
2019年4月19日
11:35
MapTask执行阶段过程
知识点
1.一个切片(InputSplit)会启动一个MapTask
2.每一个MapTask会拥有一个溢写缓冲区
3.MapTask输出的key和输出value最开始是进入到溢写缓冲区中,然后针对数据进行处理:分区以及排序
4.溢写缓冲区默认100MB,溢写80%. 即当溢写缓冲区数据达到80MB的时候,会发生Spill溢写过程
5.发生了Spill过程,就会生成一个Spill文件,存储到运行MapTask服务器的本地磁盘上
6.Spill文件的特点:是一个已分好区且已排好序的文件,比如下图所示:
7.当Spill溢写过程结束后,会发生Merge(合并).将多个Spill文件合成最终的一个结果文件.
最终的结果文件特点:已分区,并且分区内已排序的文件
8.Spill不一定会发生,即当MapTask的输出数据没有达到溢写条件
9.如果没有Spill,也就没有Merge过程.
10.如果发生了Spill过程,比如第一次spill:80MB 第二次spill:80MB, 第三次spill:20MB
针对第三次的过程,虽然没有达到80MB的溢写条件,但是要确保数据的完整性,所以此时底层会发生
Flush过程,即把内存中尾巴数据都刷出到文件里.针对上面的例子,最终会产生两个Spill文件.
11.如果发生了Spill过程,那Merge过程一定会发生吗?不一定,以为如果只有一个Spill文件的话,那么这个Spill文件就是最终的结果文件,不需要Merge
ReduceTask执行过程
12.当ReduceTask开始工作时,会去各个MapTask fetch(抓取)属于自己分区的数据
13.ReduceTask会将fetach到的数据进行和merge和sort
14.当merge和sort结束后,按相同的key合并,形成key和Iteartor形式,通过reduce()方法传给开发者
上图所演示的就是MapReduce最为核心的流程---Shuffle
Shuffle翻译:洗牌
可以这样理解:shuffle过程就是按照某种分区规则(比如Hadoop的默认hash分区),
把数据分发指定的分区里,即经过shuffle之后,数据变得有规律了.
针对Shuffle过程补充和扩展:
1.不能根据MapTask的处理输入数据量来判断输出量大小,主要需要根据Mapper组件的
代码和业务逻辑来决定的
2.每台服务器可以同时运行多个MapTask.每个MapTask都会被分配一个溢写缓冲区,以及生成
一个最终的结果文件
3.从优化的角度,我们可以调大溢写缓冲区大小,
这样可以减少Spill次数,从而减少磁盘I/O次数以提升性能.但不是不宜过大,一般可以调为:
100MB~350MB
4.溢写缓冲区,底层设计的一种环形(环写)缓冲区机制
这种机制设计的好处是可以重复利用同一块内存地址,避免频繁的地址创建的开销
此外,之所以阈值是80%,是为了避免在发生Spill磁盘溢写时,阻塞向内存中写入数据,
所以阈值参数虽然可以调节,但一般不动.所以即使调节,不要调整100%
5.从性能优化的角度,我们可以引入Combiner中间过程,可以在MapTask端提前合并,
好处是减少Spill的溢写次数,减少磁盘I/O.而且最终的数据量减少了.
从而通过网络传输的数据量减少了,节省带宽.
6.如果引入了Combiner中间过程,在溢写缓冲区中,一定会发生Combiner合并的.
但是在Merge阶段,可能会发生Combiner. Hadoop的设计者:如果Spill文件数<3个
则,Merge时不发生Combiner. 如果是>=3,才发生Combiner.
7.也可以对最终的结果文件数据进行压缩
8.对于ReduceTask的Fetch阶段,可以调整Fetch线程数,默认是5个线程.
如果调,最后接近或等于MapTask,达到并行抓取的效果
9.ReduceTask的启动时机并不是等到所有的MapTask都运行完之后才开始fetch的
而是通过一个启动比例来控制,默认5%. 比如:100个MapTask,有5个完成了,ReduceTask
就开始工作了