大数据批式计算引擎Spark---Shuffle概述 | 青训营笔记

302 阅读3分钟

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

Shuffle定义

Spark之所以出现Shuffle,主要是因为具有某种共同特征的一类数据需要最终汇聚到一个计算节点上进行计算。这些数据分布在各个存储节点上,并且由不用的计算单元进行处理,这种数据打乱然后汇聚到不同节点的过程就是Shuffle。简而言之,就是对数据进行重新分区,这其中会涉及大量的网络io和磁盘io。

shuffle表示了不同分区数据交换的过程,不同的shuffle策略性能差异较大。目前在各个引擎中shuffle都是优化的重点,在spark框架中,shuffle是支撑spark进行大规模复杂数据处理的基石。

下图是经典的MapReduce处理数据流程,我们可以看到完整的Shuffle过程。 image.png

Shuffle算子分类

Spark中会产生shuffle的算子大概可以分为以下4类 image.png repartition:分区;
ByKey: 给定一个KV对,把相同的K聚合在一起的算子;
join:  把本身没有在一起的数据按照某种条件放在一起进行计算的算子;
Distinct:  有的人把它看做一种特殊的ByKey操作。

Shuffle流程

Spark是以Shuffle为边界,将一个Job划分为不同的Stage,这些Stage构成了一个大粒度的DAG。Spark的Shuffle主要分为Shuffle Write和Shuffle Read两个阶段。

  • Shuffle Write阶段:发生在ShuffleMapTask对该Stage的最后一个RDD完成了map端的计算之后,首先会判断是否需要对计算结果进行聚合,然后将最终结果按照不同的reduce端进行区分,写入前节点的本地磁盘。
  • Shuffle Read阶段:开始于reduce端的任务读取ShuffledRDD之后,首先通过远程或者本地数据拉取获得Write阶段各个节点中属于当前任务的数据,根据数据的Key进行聚合,然后判断是否需要排序,最后生成新的RDD。

如下图所示。

image.png

执行Shuffle的主体是Stage中的并发任务,这些任务分为 ShuffleMapTaskResultTask 两大类。ShuffleMapTask要进行Shuffle,ResultTask负责返回计算结果,一个Job中只有最后一个Stage采用ResultTask,其它均为ShuffleMapTask。

如果按照map端和reduce端来分析的话,ShuffleMapTask既可以是map端任务,也可以是reduce端任务,但ResultTask只能是reduce端任务。

Shuffle优化

  1. 避免shuffle ——使用 broadcast 替代 join

  2. 使用可以 map-side 预聚合的算子

  3. Shuffle 参数优化

  4. Shuffle 倾斜优化

    • 什么叫倾斜?有什么危害

      • 在进行shuffle的时候,必须将各个节点上相同的key拉取到某个节点上的一个task来进行处理,比如按照key进行聚合或join等操作。此时如果某个key对应的数据量特别大的话,就会发生数据倾斜。数据倾斜只会发生在shuffle过程中。
      • 危害:会使得Spark作业运行得非常缓慢,甚至可能因为某个task处理的数据量过大导致内存溢出。
    • 解决倾斜方法举例

      • 过滤少数导致倾斜的key(大多数情况下,导致倾斜的key还是很多的,并不是只有少数几个)
      • 使用Hive ETL预处理数据(治标不治本,Hive ETL中还是会发生数据倾斜)
      • 提高Shuffle操作的并发度(只是缓解了数据倾斜而已,没有彻底根除问题)
      • AQE