RDD 依赖关系
1、RDD血缘关系
1) 血缘关系说明
RDD 只支持粗粒度转换,即在大量记录上执行的单个操作。将创建RDD的一系列Lineage(血统)记录下来,以便恢复丢失的分区。RDD的 Lineage 会记录 RDD 的元数据信息和转换行为,当该RDD的部分分区数据丢失时,它可以根据这些信息来重新运算
和恢复丢失的数据分区。
2) 血缘关系的作用
RDD 是不会保存数据的,如果出错了怎么办呢,没有数据找不到数据的源头,想重新执行一次都不行,所以RDD为了提供容错性,需要将RDD间的关系保存下来,一旦出现错误,可以根据血缘关系将数据源重新读取进行计算。
相当于是没有保存数据,保存了逻辑操作。
3) 代码示例
toDebugString
这个方法可以打印出每一步血缘关系,注意不是依赖关系,依赖关系只是相邻的两个,血缘关系是连续的。
package com.atguigu.bigdata.spark.core.wc.Dep
import org.apache.spark.{SparkConf, SparkContext}
//这个包是依赖关系的,可能内容有点少
class Spark01_RDD_Dep {
}
object Spark01_RDD_Dep{
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("local[*]").setAppName("RDD")
val context = new SparkContext(conf)
val rdd = context.textFile("datas/two.txt")
println(rdd.toDebugString) //这个方法会打印血缘关系,说的不是依赖,依赖是相邻两个,这个是连续多个
val mapRDD = rdd.flatMap(_.split(" "))
println(mapRDD.toDebugString)
val mapRDD2 = mapRDD.map((_, 1))
println(mapRDD2.toDebugString)
val result = mapRDD2.reduceByKey(_ + _)
println(result.toDebugString)
result.collect().foreach(println)
context.stop()
}
}
2、宽窄依赖
查看血缘关系的方法是toDebugString
,查看依赖关系的是dependencies
。Spark 中有两种依赖,一种是窄依赖OneToOne,也就是一对一的,还有一种宽依赖,也就是一对多,也被称为shuffle依赖。
1) 窄依赖
新的RDD的一个分区的数据依赖于旧的RDD一个分区的数据。这个依赖称之为OneToOne依赖。窄依赖表示每一个父(上游)RDD的 Partition 最多被子(下游)RDD的一个 Partition 使用,窄依赖我们形象的比喻为独生子女。
2) 宽依赖
新的RDD的一个分区的数据依赖于旧的RDD多个分区的数据。这个依赖称之为Shuffle依赖。宽依赖表示同一个父(上游)RDD的 Partition被多个子(下游)RDD的 Partition 依赖,会引起 Shuffle ,总结:宽依赖我们形象的比喻为多生。
3、RDD 任务划分(重点)
RDD 任务切分中间分为:Application(应用APP),Job,Stage,Task
- Application:初始化一个
SparkContext(Spark配置信息)
即生成一个 Application。 - Job:一个 Action(行动算子) 就会生成一个 Job。
- Stage:Stage 等于宽依赖(ShuffleDependency)的个数加1。
- Task:一个 Stage 阶段中,最后一个RDD的
分区个数
就是Task的个数。