Spark-Shuffle

Spark-Shuffle理解

     对spark任务划分阶段,遇到宽依赖会断开,所以在stage 与 stage 之间会产生shuffle,大多数Spark作业的性能主要就是消耗在了shuffle环节,因为该环节包含了大量的磁盘IO、序列化、网络数据传输等操作。

    负责shuffle过程的执行、计算和处理的组件主要就是ShuffleManager,也即shuffle管理器。而随着Spark的版本的发展,ShuffleManager也在不断迭代。

   ShuffleManager 大概有两个: HashShuffleManager 和 SortShuffleManager。

 历史:

                在spark 1.2以前,默认的shuffle计算引擎是HashShuffleManager;

                在spark 1.2以后的版本中,默认的ShuffleManager改成了SortShuffleManager;

                在spark 2.0以后,抛弃了 HashShuffleManager。

HashShuffleManager

假设:每个Executor只有1个CPU core,也就是说,无论这个Executor上分配多少个task线程,同一时间都只能执行一个task线程。

 上游 stage 有 2个 Executor,每个Executor 有 2 个 task。

           下游 stage 有 3个task。

shuffle write阶段:

          将相当于mapreduce的shuffle write,按照key的hash 分桶,写出中间文件。上游的每个task写自己的文件。

          写出中间文件个数 = maptask的个数 *  reducetask的个数

 上图写出的中间文件个数 = 4 * 3 = 12 

 假设上游 stage 有 10 个Executor,每个 Executor有 5 个task,下游stage 有 4 个task,写出的中间文件数 = (10 * 5) * 4 = 200 个,由此可见,shuffle write操作所产生的磁盘文件的数量是极其惊人的。

shuffle read 阶段:

           就相当于mapreduce 的 shuffle read, 每个reducetask 拉取自己的数据。

           由于shuffle write的过程中,task给下游stage的每个task都创建了一个磁盘文件,因此shuffle read的过程中,每个task只要从上游stage的所有task所在节点上,拉取属于自己的那一个磁盘文件即可。

 弊端:

        shuffle write阶段占用大量的内存空间,会导致频繁的GC,容易导致OOM;也会产生大量的小文件,写入过程中会产生大量的磁盘IO,性能受到影响。适合小数据集的处理。          

SortShuffleManager

   Spark在引入Sort-Based Shuffle以前,比较适用于中小规模的大数据处理。为了让Spark在更大规模的集群上更高性能处理更大规模的数据,于是就引入了SortShuffleManager。

 shuffle write 阶段:

  

SortShuffleManager不会为每个Reducer中的Task生成一个单独的文件,相反,会把上游中每个mapTask所有的输出数据Data只写到一个文件中。并使用了Index文件存储具体 mapTask 输出数据在该文件的位置。

        因此 上游 中的每一个mapTask中产生两个文件:Data文件 和 Index 文件,其中Data文件是存储当前Task的Shuffle输出的,而Index文件中存储了data文件中的数据通过partitioner的分类索引。

        写出文件数 = maptask的个数 * 2  (index 和  data )

        可见,SortShuffle 的产生的中间文件的多少与 上个stage 的 maptask 数量有关。

shuffle read 阶段:

    下游的Stage中的Task就是根据这个Index文件获取自己所要抓取的上游Stage中的mapShuffleMapTask产生的数据的;

总结:

Hash Shuffle:M*R;

 Sort Shuffle:2*M;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章