Spark学习笔记之RDD依赖

依赖关系

RDD是一个粗粒度的数据集,什么都可以往里面放,而且前面我们知道了转化操作会生成新的RDD,由此形成了RDD之间就形成了前后依赖关系,RDD和它依赖的父RDD(s)的关系有两种不同的类型,即窄依赖(narrow dependency)和宽依赖(wide dependency),如下图。

RDD依赖

从图中可知:

窄依赖:指每个父RDD的一个Partition最多被一个子RDD的Partition所使用,比如filter,union,map等操作都会产生窄依赖,也有说法是‘独生子女’

宽依赖:指一个父RDD的一个Partition被多个子RDD的Partition所使用,比如groupByKey(),reduceByKey(),sortByKey()等都会产生宽依赖,超生。

对于join操作有两种情况:

  • 如果两个RDD在进行join操作时,一个RDD的partition仅仅和另一个RDD中已知个数的Partition进行join,那么这种类型的join操作就是窄依赖,如图中左半部分的join操作
  • 其它情况的join操作就是宽依赖,由于是需要父RDD的所有partition进行join的转换,这就涉及到了shuffle,因此这种类型的join操作也是宽依赖

总结一下:

我们使用父RDD的Partition被子RDD的Partition所使用的个数来决定依赖关系,即:如果父RDD的一个Partition被子RDD的一个Partition所使用就是窄依赖,否则的话就是宽依赖。同时一个子RDD的Partition可以依赖多个父RDD的Partition,只要关系数量确定,也为窄依赖。
具体解释为:即子RDD的partition对父RDD依赖的Partition的数量不会随着RDD数据规模的改变而改变。即无论是有100T的数据量还是1P的数据量,在窄依赖中,子RDD所依赖的父RDD的partition的个数是确定的,而宽依赖是shuffle级别的,数据量越大,那么子RDD所依赖的父RDD的个数就越多,从而子RDD所依赖的父RDD的partition的个数也会变得越来越多。

数据流图

Spark根据RDD之间的依赖关系来为计算任务生成不同的阶段。由于窄依赖间的依赖关系是确定的,其转换处理可以在同一个线程里完成,因此窄依赖会被Spark划分到同一个Stage里面;宽依赖则只能等父RDD的shuffle流程处理完之后,在下一个stage才能开始接下来的计算。

RDD数据流

因此Spark划分stage的思路是:从后往前推,遇到宽依赖就断开划分为一个新的Stage,遇到窄依赖就将这个RDD加入该stage中。

因此如图所示,A为一个单独的Stage,CDEF均为窄依赖,为一个stage,BF为一个stage