Spark Shuffle

目录

Spark Shuffle

Shuffle Version

Shuffle阶段划分

Hash Based Shuffle Manager

未经优化的hashShuffleManager

优化后的Hash Shuffle

Sort Based Shuffle Manager

SortShuffle的普通机制

byPass机制


Shuffle Version

Spark1.1以前的版本一直是采用Hash Shuffle的实现的方式,

1.1版本时参考Hadoop MapReduce的实现开始引入Sort Shuffle,

1.5版本时开始Tungsten钨丝计划,引入UnSafe Shuffle优化内存及CPU的使用,

1.6中将Tungsten统一到Sort Shuffle中,实现自我感知选择最佳Shuffle方式,

2.0版本,Hash Shuffle已被删除,所有Shuffle方式全部统一到Sort Shuffle一个实现中。

spark缓存路径配置 spark缓存机制_数据结构

Spark中负责shuffle过程的执行、计算和处理的组件主要就是ShuffleManager,也即shuffle管理器。ShuffleManager随着Spark的发展有两种实现的方式,分别为HashShuffleManager和SortShuffleManager,因此spark的Shuffle有Hash ShuffleSort Shuffle两种。

Shuffle阶段划分

shuffle write:mapper阶段,上一个stage得到最后的结果写出

shuffle read :reduce阶段,下一个stage拉取上一个stage进行合并

Hash Based Shuffle Manager

(Spark1.1之前)

HashShuffle是根据task的计算结果的 key值的hashcode%ReduceTask 来决定放入哪一个分区,这样保证相同的数据一定放入一个分区

未经优化的hashShuffleManager

spark缓存路径配置 spark缓存机制_spark缓存路径配置_02

上游State的RDD的每一个分区对应每一个线程, 都会产生与下游相同分区数量的文件

优化后的Hash Shuffle

Shuffle write过程中,上游state的每一个RDD的每一个分区对应一个线程,不再产生 与下游state等分区数量的文件。

而是,由executor来输出与下游的RDD分区数等量的文件。(一个Executor中有多个task)

spark缓存路径配置 spark缓存机制_数据_03

 

Sort Based Shuffle Manager

sort shuffle存在两种运行的机制: 普通机制 和 bypass机制

SortShuffle的普通机制

数据会先写入一个内存数据结构中(默认5M),此时根据不同的shuffle算子,可能选用不同的数据结构。如果是reduceByKey这种聚合类的shuffle算子,那么会选用Map数据结构,一边通过Map进行聚合,一边写入内存;如果是join这种普通的shuffle算子,那么会选用Array数据结构,直接写入内存。

接着,每写一条数据进入内存数据结构之后,就会判断一下,是否达到了某个临界阈值。如果达到临界阈值的话,那么就会尝试将内存数据结构中的数据溢写到磁盘,然后清空内存数据结构

溢写的过程中,会对数据进行分区排序,排序过后,会分批将数据写入磁盘文件。默认的batch数量是10000条

一个task将所有数据写入内存数据结构的过程中,会发生多次磁盘溢写操作,也就会产生多个临时文件。最后会将之前所有的临时磁盘文件都进行合并成1个磁盘文件

一个task就只对应一个磁盘文件,也就意味着该task为Reduce端的stage的task准备的数据都在这一个文件中,因此还会单独写一份索引文件,其中标识了下游各个task的数据在文件中的start offset与end offset。

spark缓存路径配置 spark缓存机制_数据结构_04

 

byPass机制

bypass运行机制的触发条件如下:

  1. 第一 ,shuffle map task数量小于spark.shuffle.sort.bypassMergeThreshold=200参数的值;

第二,不是map combine聚合的shuffle算子(比如reduceByKey有map combie)

task会为每个reduce端的task都创建一个临时磁盘文件,并将数据按key进行hash,然后根据key的hash值,将key 溢写 到对应磁盘文件

spark缓存路径配置 spark缓存机制_spark_05

 

该过程的磁盘写机制其实跟未经优化的HashShuffleManager一样,因为都要创建数量惊人的磁盘文件,只是在最后会做一个磁盘文件的合并而已。因此少量的最终磁盘文件,也让该机制相对未经优化的HashShuffleManager来说,shuffle read的性能更好。

与SortShuffle普通机制的区别在于:

第一,磁盘写机制不同;

第二,不会进行排序。也就是说,启用该机制的最大好处在于,shuffle write过程中,不需要进行数据的排序操作

相关参数

参数

参数说明

spark.shuffle.file.buffer

该参数用于设置shuffle write task的BufferedOutputStream的buffer缓冲大小(默认是32K)。将数据写到磁盘文件之前,会先写入buffer缓冲中,待缓冲写满之后,才会溢写到磁盘。

spark.reducer.maxSizeInFlight

该参数用于设置shuffle read task的buffer缓冲大小,而这个buffer缓冲决定了每次能够拉取多少数据。(默认48M)

spark.shuffle.io.maxRetries

shuffle read task从shuffle write task所在节点拉取属于自己的数据时,如果因为网络异常导致拉取失败,是会自动进行重试的。该参数就代表了可以重试的最大次数。(默认是3次)

spark.shuffle.io.retryWait

该参数代表了每次重试拉取数据的等待间隔。(默认为5s) 调优建议:一般的调优都是将重试次数调高,不调整时间间隔。

spark.shuffle.memoryFraction

该参数代表了Executor内存中,分配给shuffle read task进行聚合操作内存比例。

spark.shuffle.manager

该参数用于设置shufflemanager的类型(默认为sort)


Hash:spark1.x版本的默认值,HashShuffleManager


Sort:spark2.x版本的默认值,普通机制,当shuffle read task 的数量小于等于spark.shuffle.sort.bypassMergeThreshold参数,自动开启bypass 机制

spark.shuffle.sort.bypassMergeThreshold

当ShuffleManager为SortShuffleManager时,如果shuffle map task的数量小于这个阈值(默认是200),则shuffle write过程中不会进行排序操作。