上篇文章 spark 源码分析之十八 -- Spark存储体系剖析 重点剖析了 Spark的存储体系。从本篇文章开始,剖析Spark作业的调度和计算体系。
在说DAG之前,先简单说一下RDD。
对RDD的整体概括文档说明如下:
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函数,如下:
注意:这只是常见的函数,并没有列举所有的action函数。
Action函数的特点那么action函数有哪些特点呢?
根据上面介绍的,即action会返回一个值给driver节点。即它们的函数返回值是一个具体的非RDD类型的值或Unit,而不是RDD类型的值。
Transformation函数官方提供了Transform 函数,如下:
Transformation函数的特点上文提到,transformation接收一个存在的数据集,并将计算结果作为新的RDD返回。也是就说,它的返回结果是RDD。
总结
其实,理解了action和transformation的特点,看函数的定义就知道是action还是transformation。
RDD的依赖关系
官方文档里,聊完RDD的操作,紧接着就聊了一下shuffle,我们按照这样的顺序来做一下说明。
Shuffle官方给出的shuffle的解释如下:
注意: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过程的。
如图:
这张图也说明了一个结论,并不是所有的join都是宽依赖。
依赖关系在源码中的体现我们通常说的 RDD,在Spark中具体表现为一个抽象类,所有的RDD子类继承自该RDD,全称为 org.apache.spark.rdd.RDD,如下:
它有两个参数,一个参数是SparkContext,另一个是deps,即Dependency集合,Dependency是所有依赖的公共父类,即deps保存了父类的依赖关系。
其中,窄依赖的父类是 NarrowDependency, 它的构造方法里是由父RDD这个参数的,宽依赖 ShuffleDependency ,它的构造方法里也是有父RDD这个参数的。
RDD 依赖关系的不确定性 getDependencies 方法获取抽象的方法是 getDependencies 方法,如下: