Shuffle原理剖析与源码分析

文章转自:http://blog.csdn.net/github_36444580/article/details/78637355git

对比Spark与MR中的shuffle

1.Shuffle是MapReduce框架中的一个特定的phase(时期),介于Map phase和Reduce phase之间,当Map的输出结果要被Reduce使用时,输出结果须要按key哈希,而且分发到每个Reducer上去,这个过程就是shuffle。因为shuffle涉及到了磁盘的读写和网络的传输,所以shuffle性能的高低直接影响到了整个程序的的运行效率。一样在spark中也存在shuffle。github

2.Spark中,reduceByKey会将上一个RDD中的每个key对应的全部value聚合成一个value,而后生成一个新的RDD,元素类型是<key,value>对的形式,这样每个key对应一个聚合起来的value。每个key对应的value不必定都是在一个partition中,也不太可能在同一个节点上,由于RDD是分布式的弹性的数据集,他的partition极有可能分布在各个节点上。缓存

3.聚合操做分为两个阶段网络

1>Shuffle Write:上一个stage的每一个map task就必须保证将本身处理的当前分区的数据相同的key写入一个分区文件中,可能会写入多个不一样的分区文件中。框架

2>Shuffle Read:reduce task就会从上一个stage的全部task所在的机器上寻找属于本身的那些分区文件,这样就能够保证每个key所对应的value都会汇聚到同一个节点上去处理和聚合。
分布式

Shuffle原理剖析与源码分析

一、在Spark中,什么状况下,会发生shuffle?reduceByKey、groupByKey、sortByKey、countByKey、join、cogroup等操做。
二、默认的Shuffle操做的原理剖析
三、优化后的Shuffle操做的原理剖析
四、Shuffle相关源码分析
普通的shuffle:
优化后的shuffle:


spark shuffle操做的两个特色

第一个特色,
    在Spark早期版本中,那个bucket缓存是很是很是重要的,由于须要将一个ShuffleMapTask全部的数据都写入内存缓存以后,才会刷新到磁盘。可是这就有一个问题,若是map side数据过多,那么很容易形成内存溢出。因此spark在新版本中,优化了,默认那个内存缓存是100kb,而后呢,写入一点数据达到了刷新到磁盘的阈值以后,就会将数据一点一点地刷新到磁盘。
    这种操做的优势,是不容易发生内存溢出。缺点在于,若是内存缓存太小的话,那么可能发生过多的磁盘写io操做。因此,这里的内存缓存大小,是能够根据实际的业务状况进行优化的。

第二个特色,
    与MapReduce彻底不同的是,MapReduce它必须将全部的数据都写入本地磁盘文件之后,才能启动reduce操做,来拉取数据。为何?由于mapreduce要实现默认的根据key的排序!因此要排序,确定得写完全部数据,才能排序,而后reduce来拉取。
    可是Spark不须要,spark默认状况下,是不会对数据进行排序的。所以ShuffleMapTask每写入一点数据,ResultTask就能够拉取一点数据,而后在本地执行咱们定义的聚合函数和算子,进行计算。
    spark这种机制的好处在于,速度比mapreduce快多了。可是也有一个问题,mapreduce提供的reduce,是能够处理每一个key对应的value上的,很方便。可是spark中,因为这种实时拉取的机制,所以提供不了,直接处理key对应的values的算子,只能经过groupByKey,先shuffle,有一个MapPartitionsRDD,而后用map算子,来处理每一个key对应的values。就没有mapreduce的计算模型那么方便。