一、为什么要设计宽窄依赖
- 对于窄依赖,Spark可以并行计算。如果有一个分区数据丢失,只需要从父RDD的对应1个分区重新计算即可,不需要重新计算整个任务,提高容错
- 对于宽依赖,是划分Stage的依据
- 构建Lineage血缘关系,RDD只支持粗粒度转换,即只记录单个块上执行的单个操作。将创建RDD的一系列Lineage(血统)记录下来,以便恢复丢失的数据。RDD的Lineage会记录RDD的元数据信息和转换行为,当该RDD的部分分区数据丢失时,它可以根据这些信息来重新运算和恢复丢失的数据分区
二、窄依赖
窄依赖中:即父RDD与子RDD件2的分区是一对一的。换句话说父RDD中,一个分区内的数据是不能被分割的,只能由子RDD中的一个分区整个利用
上图中 P代表 RDD中的每个分区(Partition),我们看到,RDD 中每个分区内的数据在上面的几种转移操作之后被一个分区所使用,即其依赖的父分区只有一个。比如图中的 map、union 和 join 操作,都是窄依赖的。注意,join 操作比较特殊,可能同时存在宽、窄依赖。
三、Shuffle依赖(宽依赖 Wide Dependency)
Shuffle有“洗牌、搅乱”的意思,这里所谓的Shuffle依赖也会打乱原RDD结构的操作。具体来说,父RDD中的分区可能会被多个子RDD分区使用。因为父RDD中一个分区内的数据会被分割并发送给子RDD的所有分区,因此Shuffle依赖也意为着父RDD与子RDD之间存在着Shuffle过程
上图中 P 代表 RDD 中的多个分区,我们会发现对于 Shuffle 类操作而言,结果 RDD 中的每个分区可能会依赖多个父 RDD 中的分区。需要说明的是,依赖关系是 RDD 到 RDD 之间的一种映射关系,是两个 RDD 之间的依赖,如果在一次操作中涉及多个父 RDD,也有可能同时包含窄依赖和 Shuffle 依赖。
四、如何区分宽窄依赖
区分RDD之间的依赖为宽依赖还是窄依赖,主要在于父RDD分区数据与子RDD分区数据关系:
- 窄依赖:父RDD的一个分区只会被子RDD的一个分区依赖
- 宽依赖:父RDD的一个分区会被子RDD的多个分区依赖,设计Shuffle