【Spark】Spark Shuffle 原理

  今天学习 Spark Shuffle。昨天文章提到了 Spark 划分 stage 时,分为了 ShuffleMapStage 和 ResultStage。没看过的可以看昨天的文章。

【Spark】Spark 任务调度

【Spark】Spark Shuffle 原理_第1张图片

在划分 stage 时:

  • 前面的所有 stage 被称为 ShuffleMapStage。ShuffleMapStage 的结束伴随着 shuffle 文件的写磁盘。
  • 最后一个 stage 称为 finalStage,它本质上是一个 ResultStage 对象,ResultStage 对应代码中的 action 算子,将一个函数应用在 RDD 的各个 partition 的数据集上,意味着一个 job 的运行结束。

下面讲 Spark 的两种 Shuffle。

1.HashShuffle

1.1 未优化的 HashShuffle

假设每个 Executor 只有 1 个 CPU core,无论这个 Executor上分配多少个 Task 线程,同一时间都只能执行一个 Task 线程。例如 3 个 Reducer,具体过程如下:

  • 在 Task 中进行 Hash 计算,分区器计算分区(hash 值 % num_reduce,这里是 3),得到 3 个不同的分区(3 类数据);
  • 想把不同的数据汇聚然后计算出最终的结果,Reducer 会在每个 Task 中把属于自己类别的数据收集过来,汇聚成一个同类别的大集合;
  • 总文件数:每 1 个 Task 输出 3 份本地文件,这里有 4 个 Mapper Tasks,所以总共输出了 4 x 3 = 12 个本地小文件。

【Spark】Spark Shuffle 原理_第2张图片

1.2 优化后的 HashShuffle

优化的 HashShuffle 过程就是启用合并机制,合并机制就是复用 buffer,开启合并机制的配置是 spark.shuffle.consolidateFiles。该参数默认值为 false,将其设置为 true 即可开启优化机制。还是上面的例子,过程如下:

  • 在同一个进程中,无论是有多少过 Task,都会把同样的 Key 放在同一个 Buffer 里;
  • 然后把 Buffer 中的数据写入以 Core 数量为单位的本地文件中,所以这里是每个 Core 只产出了 3 份本地文件;
  • 这里有 2 个 Core 4个 Mapper Tasks,所以总共输出是 2 x 3 = 6 个本地小文件。

【Spark】Spark Shuffle 原理_第3张图片

2.SortShuffle 解析

2.1 普通 SortShuffle

在该模式下,数据会先写入一个数据结构:

  • reduceByKey 写入 Map,一边通过 Map 局部聚合,一边写入内存;
  • Join 算子写入 ArrayList 直接写入内存中。然后需要判断是否达到阈值,如果达到就会将内存数据结构的数据写入到磁盘,清空内存数据结构。

之后开始溢写磁盘,具体步骤:

  • 先根据 key 进行排序;
  • 排序过后的数据,会分批写入到磁盘文件中。默认数据会以每批 10000 条写入到磁盘文件。
  • 写入磁盘文件通过缓冲区溢写的方式,每次溢写都会产生一个磁盘文件,也就是说一个 Task 过程会产生多个临时文件。
  • 最后在每个Task中,将所有的临时文件合并,这就是 merge 过程,此过程将所有临时文件读取出来,一次写入到最终文件。

最终一个 Task 的所有数据都在这一个文件中。同时单独写一份索引文件,标识下游各个 Task 的数据在文件中的索引(start offset和end offset)。

【Spark】Spark Shuffle 原理_第4张图片

2.2 bypass SortShuffle

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

  • shuffle reduce task数量小于 spark.shuffle.sort.bypassMergeThreshold 参数的值,默认为 200;
  • 不是聚合类的shuffle算子(比如reduceByKey)。

执行过程:

  • Task 为每个 reduce 端的 Task 都创建一个临时磁盘文件;
  • 将数据按 key 进行 hash,然后根据 key 的 hash 值,将 key 写入对应的磁盘文件之中;
  • 写入磁盘文件时也是先写入内存缓冲,缓冲写满之后再溢写到磁盘文件的;
  • 最后,将所有临时磁盘文件都合并成一个磁盘文件,并创建一个单独的索引文件。

与 HashShuffler 对比:

  • 该过程的磁盘写机制跟未经优化的 HashShuffleManager 是一模一样的,因为都要创建大量磁盘文件;
  • bypass SortShuffle 在最后会做一个磁盘文件的合并,因此只生成少量的最终磁盘文件,因此相对未经优化的 HashShuffleManager 来说,shuffle read 的性能会更好。

与普通的 ShortShuffler 对比:

  • 不会进行排序。也就是说,启用该机制的最大好处在于,shuffle write 过程中,不需要进行数据的排序操作,也就节省掉了这部分的性能开销。

【Spark】Spark Shuffle 原理_第5张图片
欢迎关注。
【Spark】Spark Shuffle 原理_第6张图片

你可能感兴趣的:(Spark,大数据,spark)