Dependency的类型
rdd的Dependency分NarrowDependency和ShuffleDependency两种。
1 NarrowDependency:一个Parent RDD的数据经过处理之后,只能传递到一个Child RDD,它又分为:
a. OneToOneDependency:MapPartitionsRDD、HadoopRDD的依赖,这种依赖Parent RDD和Child RDD是1对1的关系
b. RangeDependency:UnionRDD的依赖,这种依赖是多个Parent RDD对应1个Child RDD
2 ShuffleDependency: 一个Parent RDD的数据经过处理之后,传递给多个Child RDD,ShuffledRDD的依赖就是这种类型。
rdd的dependencies是如何初始化的:
rdd都继承自 class RDD,来看下它的主构造函数:
abstract class RDD[T: ClassTag](
@transient private var _sc: SparkContext,
// 参数deps即该rdd的依赖s
@transient private var deps: Seq[Dependency[_]]
) extends Serializable with Logging
rdd的依赖应该都来自这个deps了,那deps怎么来的呢,以rdd.map来看下:
// 以 rdd_A.map(...) 为例
def map[U: ClassTag](f: T => U): RDD[U] = withScope {
val cleanF = sc.clean(f)
// 新建 MapPartitionsRDD 对象,将 rdd_A 本身作为第一个参数
new MapPartitionsRDD[U, T](this, (context, pid, iter) => iter.map(cleanF))
}
再看MapPartitionsRDD的定义(主构造函数):
private[spark] class MapPartitionsRDD[U: ClassTag, T: ClassTag](
prev: RDD[T],
f: (TaskContext, Int, Iterator[T]) => Iterator[U],
preservesPartitioning: Boolean = false)
extends RDD[U](prev)
MapPartitionsRDD 第一个参数prev来自父类RDD,构造 MapPartitionsRDD 时先调用 super(prev), 即调RDD的构造函数。
super(prev)
=> 调 RDD私有构造函数:
// oneParent 即rdd_A对象
def this(@transient oneParent: RDD[_]) = this(
oneParent.context ,
List(new OneToOneDependency(oneParent)))
=> 调 RDD主构造函数:
RDD[T: ClassTag](
@transient private var _sc: SparkContext,
@transient private var deps: Seq[Dependency[_]])
可以看到rdd_A对象被封装为List传入RDD主构造函数,的第二个参数即其 deps ;
再看 r.dependencies 方法:
final def dependencies: Seq[Dependency[_]] = {
checkpointRDD.map(r => List(new OneToOneDependency(r))).getOrElse {
if (dependencies_ == null) {
// 这里即返回 RDD 主构造函数参数 deps ;
dependencies_ = getDependencies
}
dependencies_
}
}