spark 源码分析之十九 -- DAG的生成和Stage的划分

上篇文章 spark 源码分析之十八 -- Spark存储体系剖析 重点剖析了 Spark的存储体系。从本篇文章开始,剖析Spark作业的调度和计算体系。

在说DAG之前,先简单说一下RDD。

对RDD的整体概括

文档说明如下:

spark 源码分析之十九 -- DAG的生成和Stage的划分

RDD全称Resilient Distributed Dataset,即分布式弹性数据集。它是Spark的基本抽象,代表不可变的可分区的可并行计算的数据集。

RDD的特点:

1. 包含了一系列的分区

2. 在每一个split上执行函数计算

3. 依赖于其他的RDD

4. 对于key-value对的有partitioner

5. 每一个计算有优先计算位置

更多内容可以去看Spark的论文:

RDD的操作

RDD支持两种类型的操作:

transformation:它从已存在的数据集中创建一个新的数据集。它是懒执行的,即生成RDD的所有操作都是懒执行的,也就是说不会马上计算出结果,它们只会记住它们依赖的基础数据集(文件、MQ等等),等到一个action需要结果返回到driver端的时候,才会执行transform的计算。这种设计使得RDD计算更加高效。

action:它在数据集上运行计算之后给driver端返回一个值。

注意:reduce 是一个action,而 reduceByKey 则是一个transform,因为它返回的是一个分布式数据集,并没有把数据返回给driver节点。

Action函数

官方提供了RDD的action函数,如下:

spark 源码分析之十九 -- DAG的生成和Stage的划分

注意:这只是常见的函数,并没有列举所有的action函数。

Action函数的特点

那么action函数有哪些特点呢?

根据上面介绍的,即action会返回一个值给driver节点。即它们的函数返回值是一个具体的非RDD类型的值或Unit,而不是RDD类型的值。

Transformation函数

官方提供了Transform 函数,如下:

spark 源码分析之十九 -- DAG的生成和Stage的划分

Transformation函数的特点

上文提到,transformation接收一个存在的数据集,并将计算结果作为新的RDD返回。也是就说,它的返回结果是RDD。

 

总结

其实,理解了action和transformation的特点,看函数的定义就知道是action还是transformation。

 

RDD的依赖关系

官方文档里,聊完RDD的操作,紧接着就聊了一下shuffle,我们按照这样的顺序来做一下说明。

Shuffle

官方给出的shuffle的解释如下:

spark 源码分析之十九 -- DAG的生成和Stage的划分

注意:shuffle是特定操作才会发生的事情,这跟action和transformation划分没有关系。

官方给出了一些常见的例子。

Operations which can cause a shuffle include repartition operations like  and , ByKey operations (except for counting) like  and , and join operations like  and .

RDD的四种依赖关系

那么shuffle跟什么有关系呢?

shuffle跟依赖有关系。在 spark 源码分析之一 -- RDD的四种依赖关系 中,说到 RDD 分为宽依赖和窄依赖,其中窄依赖有三种,一对一依赖、Range依赖、Prune 依赖。宽依赖只有一种,那就是 shuffle 依赖。

即RDD跟父RDD的依赖关系是宽依赖,那么就是父RDD在生成新的子RDD的过程中是存在shuffle过程的。

如图:

spark 源码分析之十九 -- DAG的生成和Stage的划分

这张图也说明了一个结论,并不是所有的join都是宽依赖。

依赖关系在源码中的体现

我们通常说的 RDD,在Spark中具体表现为一个抽象类,所有的RDD子类继承自该RDD,全称为 org.apache.spark.rdd.RDD,如下:

spark 源码分析之十九 -- DAG的生成和Stage的划分

它有两个参数,一个参数是SparkContext,另一个是deps,即Dependency集合,Dependency是所有依赖的公共父类,即deps保存了父类的依赖关系。

其中,窄依赖的父类是 NarrowDependency, 它的构造方法里是由父RDD这个参数的,宽依赖 ShuffleDependency ,它的构造方法里也是有父RDD这个参数的。

RDD 依赖关系的不确定性 getDependencies 方法

获取抽象的方法是 getDependencies 方法,如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwwwzz.html