1.概述
众所周知,RDD有五大特性.
i). A list of partitions
RDD是由多个分区(partition)组成的一个集合
ii). A function for computing each split
对RDD的每一个计算,等于对这个RDD的每一个分区执行一个计算
iii). A list of dependencies on other RDDs
每一个RDD都会记录它的父RDD的依赖(如果是第一个,则会是对数据源的依赖)
iv). Optionally, a Partitioner for key-value RDDs (e.g. to say that the RDD is hash-partitioned)
如果RDD里存放的是Key-Value的形式.则可以传入一个自定义的分区函数进行分区(比如自定义按Key分区,则会将不同RDD的相同Key都集中在一个Partition中)
v). Optionally, a list of preferred locations to compute each split on (e.g. block locations for an HDFS file)
计算就近原则.计算会尽可能的放入split所在的节点中
接下来从源码角度,体现出这五大特性
2.这耳熟能详的五大特性的真正出处
3.五大特性的源码体现如下:
/** * Implemented by subclasses to compute a given partition. * * 可以看出compute是所有RDD子类都必须实现的 用于计算给定的分区的 抽象方法.. * 注意这里 compute的入参是 split: Partition 因此所有的计算都是以Partition为基准的(特性2) */ @DeveloperApi def compute(split: Partition, context: TaskContext): Iterator[T] /** * Implemented by subclasses to return the set of partitions in this RDD. This method will only * be called once, so it is safe to implement a time-consuming computation in it. * * The partitions in this array must satisfy the following property: * `rdd.partitions.zipWithIndex.forall { case (partition, index) => partition.index == index }` * * 可以看出 getPartitions 是所有RDD子类都必须实现的. 用于返回RDD的分区集 * 这也说明 RDD 本身是由 Partition(分区) 组成的 (特性1) * 另外:这个方法只会被调用一次. 这说明了RDD的一个隐藏特性: RDD是不可变的 */ protected def getPartitions: Array[Partition] /** * Implemented by subclasses to return how this RDD depends on parent RDDs. This method will only * be called once, so it is safe to implement a time-consuming computation in it. * * getDependencies 获取这个RDD的依赖关系. 注意: deps 是由RDD的构造传入的. * 这说明 RDD必然会记录它依赖(构造必须传入) (特性3) */ protected def getDependencies: Seq[Dependency[_]] = deps /** * Optionally overridden by subclasses to specify placement preferences. * * getPreferredLocations 获取这个RDD存储路径. Seq[String] 因为有副本概念.Seq(0)就是首选地址 (特性5) */ protected def getPreferredLocations(split: Partition): Seq[String] = Nil /** Optionally overridden by subclasses to specify how they are partitioned. * * partitioner 分区函数. 如果需要就可以自定义分区算法覆盖分区函数 (特性4) */ @transient val partitioner: Option[Partitioner] = None