开发者学堂课程【大数据 Spark 2020版(知识精讲与实战演练)第三阶段:Spark 原理_逻辑图_窄依赖的分类_分析】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/689/detail/12019
Spark 原理_逻辑图_窄依赖的分类_分析
内容简介
一、了解依赖类
二、一对一窄依赖
三、Range 窄依赖
四、多对一窄依赖
五、谈宽窄依赖的区别
一、了解依赖类
上节通过源码了解了依赖类的继承关系,从源码上看到依赖关系:
1.最顶级、外部的类叫做 dependency,其有两个直接子类:shuffledependency、narrowdependency
2.Narrowdependency 类含有两个子类:一对一窄依赖、range 窄依赖,以及一个逻辑窄依赖:一对多窄依赖
进入笔记中,有明确的窄依赖的三张图
二、一对一窄依赖
其实 RDD 中默认的是 onetoonedependency,后被不同的 RDD 子类指定为其他的依赖类型,常见的一堆依赖是 map 算子所产生的依赖,一对一窄依赖怎样会出现,例如 rddB = rddA.map(...)
// onetoonedependency 就是一对一窄依赖,在前面见到过,如果一个 RDD 的子类中,没有重写 getdependency 方法,rdd 默认的 dependency 返回的就是 onetoonedependency
每个分区之间一一对应,所以叫做一对一窄依赖,rddA 的p1与 rddB 的 p1 是一对一关系
三、Range 窄依赖
Range 窄依赖其实也是一对一窄依赖,但是保留了中间的分隔信息,可以通过某个分区获取其父分区,目前只有一个算子生成这种窄依赖,就是 union 算子,例如,rddC = rddA.union(rddB)
//Union 就是把两个集合合并,求其并集
接下里我们要做的就是将 rddA 和 rddB union 起来
RddA 的第一个分区,对应了 rddC 中的第一个分区;RddA 的第二个分区,对应了 rddC 中的第二个分区;RddA 的第三个分区,对应了 rddC 中的第三个分区;rddB 中的第一个分区对应了 rddC 中的 p4;rddB 中的第二个分区对应了 rddC 中的 p5,如图箭头所示
所以还是一对一依赖。
例如要通过 p4 了解父 rdd 是谁,那么这个时候要知道是 rddB 才行,所以就设定了一个边界,在 p3 和 p4 中间画了一条线,要记录 rddA 分区的 rdd 起始自那个下标,结束自那个下标,记录每个 rdd 在这个结果 rdd 中的 range,这称之为 range 窄依赖,本质上还是一对一,而且只在 union 中使用,所以我们简单了解一下。
1.RddC 其实就是 rddA 拼接 rddB 生成的,所以 rddC 的 p1 和p4,分别对应 rddA 的 p1和 rddB 的 p1
2.所以需要有方式获取到 rddC 的 p4 其父分区是谁,于是就需要记录以下边界,记录每个分区的 range,其他部分和一对一窄依赖一样
四、多对一窄依赖
多对一窄依赖相对来说不太好理解,但是我们也可以简单看一下,多对一窄依赖有非常明显的场景,coalesce(减少分区)
多对一窄依赖其图形和 shuffle 依赖非常相似,所以在遇到的时候,要注意其 RDD 之间是否有 shuffle 过程,比较容易让人困惑,常见的多对一依赖就是重分区算子 coalesce,常见的 rddB = rddA.coalesce(2,shuffle = false),但同时也要注意,如果 shuffle = true 那就是完全不同的情况了
1.当将三个分区减少为两个分区时,势必要合并其中两个分区,所以 coalesce 就是一对多依赖
2.右边(合并后)的 p3 依赖了左边的 p2 和 p3,这就是多对一关系
//因为 左边的 p2 和 p3 将数据都传到了 右边的 p3,这是多对一关系,p2 和 p3 将数据全部给 p3,不存在 shuffle 过程,所以这同样时窄依赖
//Coalesce 可以指定是否 shuffle,当指定不 shuffle,coalesce 是不会生成 shuffle 依赖,只会生成窄依赖
五、谈宽窄依赖的区别
1.区别就是界定两个分区,是否可以放到同一流水线上执行
举例
(1)多对一窄依赖图例,如上图:
要计算右边 p1 的数据时,可以直接通过左边 p1 获得当要计算右边 p3 的数据时,直接通过左边的 p2、p3获得,不需要p1 ,不存在 shuffle 过程,但中间需要算子计算。
(2)一对一窄依赖图例,如上图:
RddA 的 p1和 rddB 的 p1可以放在一个任务中运行,当需要 rddB 的 p1 中的数据时,可以直接通过 rddA 的 p1 进行过渡。
2. 划分宽窄依赖的核心区别是:窄依赖的RDD 中对应的分区可以放在一个 tesk 中运行
窄依赖的 rdd 的所有分区,假如有三个 rdd 是窄依赖关系,那么他们三个 rdd 的对应分区是可以放在一个 task 中去运行的,这是我们所说的窄依赖。
然而宽依赖并不适用,如下 reducebykey 例子:
计算 rddB 中 p1 的数据,它依赖于 rddA 中的所有分区,需要将数据都计算好,一个一个获取,都计算好才能进行 shuffle,这是他们间的最大区别。
它们之间的最大区别就是:窄依赖的 rdd 可以放在一个 task 中运行。