每个RDD都有其对应的依赖,依次索引,就可以追踪到起始RDD(其依赖为空)
当前RDD的逻辑处理都是对其父RDD的操作,当前RDD数据是对其父RDD数据做compute(~)获得的,这种操作实现了RDD的惰性加载
spark RRD 依赖关系:
窄依赖:每个父RRD的分区至多被一个子RDD的分区使用,协同划分,分区一一对应。
宽依赖:多个子RDD的分区依赖一个父RDD的分区。多对多的关系,宽依赖需要所有的父RDD分区数据可用。
宽依赖操作会有一个可选参数(手动设置分区数)。
spark默认提供两种分区划分器,且只针对(k,v)类型的RDD
1,哈希分区划分器:HashPartitioner
2,范围分区划分器:RangePartitioner =》猜测:自定义Partitioner控制分区数据
RDD是抽象类,主构造函数参数:
abstract class RDD[T: ClassTag]( @transient private var _sc: SparkContext, @transient private var deps: Seq[Dependency[_]] )
辅助构造器参数:是其父RDD;如是实现了RDD的血缘传递,延迟加载。
/** Construct an RDD with just a one-to-one dependency on one parent */ def this(@transient oneParent: RDD[_]) = this(oneParent.context , List(new OneToOneDependency(oneParent)))
RDD的实现类(窄依赖): 如MapPartitionsRDD
如上:当前RDD的所有实现都是对其父RDD的操作
主构造器参数:
prev:父RDD
f : 处理父RDD的函数
preservesPartitioning : 是否使用父RDD的partitioner
重写的RDD的compute(~)方法: 函数 f 处理父RDD获得的数据(当前RDD 计算所需要的数据)
RDD获取分区数据(惰性加载)
1,缓存中有的话直接取出来用
2,缓存中没有,只能通过compute(~)处理父RDD数据获取当前RDD数据
3,逆向递归,处理1,2逻辑
/** * Internal method to this RDD; will read from cache if applicable, or otherwise compute it. * This should ''not'' be called by users directly, but is available for implementors of custom * subclasses of RDD. */ final def iterator(split: Partition, context: TaskContext): Iterator[T] = { if (storageLevel != StorageLevel.NONE) { SparkEnv.get.cacheManager.getOrCompute(this, split, context, storageLevel) } else { computeOrReadCheckpoint(split, context) } }