Spark依赖分为宽依赖和窄依赖:
窄依赖
子RDD的每个分区依赖于常数个(即与数据规模无关)
输入输出一对一的算子,且结果RDD的分区结构不变,主要是map、flatMap
输入输出一对一,但结果RDD的分区结构发生了变化,如 union、coalesce
从输入中选择部分元素的算子,如filter、distinct、subtract、sample
宽依赖
子RDD的每个分区依赖于所有父RDD分区
对单个RDD基于key进行重组和reduce,如 groupByKey、reduceByKey‘
对两个RDD基于key进行join和重组,如join
区分宽依赖和窄依赖是根据父RDD的每个分区数据给多少个子RDD的每个分区数据:
1 -> 1 :窄依赖
1 -> N :宽依赖,有宽依赖的地方必有shuffle
Spark Shuffle
Shuffle过程的解析
在Spark RDD的计算处理的过程中,每个宽依赖都伴随着Shuffle。
首先看Shuffle过程
依图所示:
假设有一个节点,上面运行了3个shuffleMapTask,每个shuffleMapTask,都会为每个ReduceTask创建一份bucket缓存以及对应的ShuffleBlockFile磁盘文件,shuffleMapTask的输出,会作为MapStatus,发送到DAGScheduler的MapOutputTrackerMaster中,每个MapStatus包含了每个ReduceTask要拉取的数据的大小。
假设有另外一个节点,上面也运行了4个ReduceTask,现在等着去获取ShuffleMapTask的输出数据,来完成程序定义的算子,而ReduceTask会用BlockStoreShuffleFetcher去MapOutputTrackerMaster获取自己要拉取的文件的信息,然后底层通过BlockManager将数据拉取过来。每个ReduceTask拉取过来的数据,其实就会组成一个内部的RDD,叫shuffleRDD,优先放入内存,其次如果内存不够,那么写入磁盘,最后每个ReduceTask针对数据进行聚合,最后生成MapPartitionRDD,就是执行reduceByKey等操作希望获得的RDD。