shuffle 原理 | 青训营笔记

116 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的第5天

shuffle 概念起源于Map Reduce计算模型。 Map Reduce期望实现多机器的分布式并行计算,并让每个机器尽量少的交换数据。 基于这个思路,简单来说shuffle就是插在Map和Reduce之间的一个阶段,当完成了Map之后,在shuffle阶段把数据转移到应该在的位置上, 以便于Reduce操作,这样 Map 和 Reduce 就是单机运算了。

shuffle 阶段对整体性能至关重要,这里有大量的数据传输,甚至有计算操作,设计到计算和网络传输两个方面。

尽管近些年计算引擎发展迭代日新月异,但是仍然是有shuffle阶段的。

以Spark 3.2为例,其shuffle算子就可分为四类 repartition、byKey、join、distinct。

spark 通过所谓的RDD依赖关系处理shuffle。Spark 自身有过许多次的shuffle算法迭代,不过基本上还是可以分为两类。 一是hash shuffle,二是sort shuffle。

对于 Hash shuffle 而言,所谓的hash表实际上是文件,从某种意义上来说可以认为是使用了文件系统的B树实现的hash表。具体的数据通过hash函数保存的文件中。这其实有一些隐患,因为文件的数量和hash表的大小一致,而文件数据一旦变多会因为太多的文件io影响到程序运行的效率。

sort shuffle与hash shuffle不同,它把文件内部切分了不同的区域或者说片段,用以实现类似的效果。这可以避免上面说的重要的隐患:过多的挂起的待处理IO对象。

另外是并行度的问题,shuffle并行度较低的时候容易造成热点分区现象,这样的数据倾斜问题会让效率降低。简单的缓解措施就是提高并行度,稍微降低倾斜问题,其次则是Spark 提供的另一种机制,对于数据过多的时候自动分裂成两个任务。