一.理解RDD 是什么

RDD的全称是:Resilient Distributed Dataset (弹性分布式数据集),它有几个关键的特性:

  1. RDD是只读的,表示它的不可变性。可以并行的操作分区集合上的所有元素。

怎么做到的呢?我们可以从RDD的内部实现来进行了解。

每个RDD的内部,有5个主要特性:

  1. A list of partitions (一个分区列表,可以获取所有的数据分区)A function for computing each split(对给定的分区内的数据进行计算的function)A list of dependencies on other RDDs (一个RDD所依赖的父RDD列表)Optionally, a Partitioner for key-value RDDs (可选:如何进行K-V的RDD分区)Optionally, a list of preferred locations to compute each split on(可选:数据做运算时最优的地址,即数据本地性)

以上对应的方法或属性如下:

protected def getPartitions: Array[Partition]
 def compute(split: Partition, context: TaskContext): Iterator[T]
 protected def getDependencies: Seq[Dependency[_]] = deps
 @transient val partitioner: Option[Partitioner] = None
 protected def getPreferredLocations(split: Partition): Seq[String] = Nil

有了这些特性,再返回来理解RDD描述的 “弹性分布式数据集” 是怎么做到呢?

依赖的父RDD列表,当分布式计算时,有失败的任务时,可以再通过 deps 重新生成;这体现的是弹性;而compute与getPartitons一起来完成分布式计算,一个是提供数据,一个是提供操作于所有数据的执行运算的能力。

其中,以能够提供本地化计算的标准,来评价一个组件与spark接合的是否完美。比如HDFS上面的parquet文件,可以完美的做到本地化;而像HBase就不能(目前到spark 2.3.0版本还未能实现),本地化的运算,是分布式计算的根本,即搬运的是函数,而不搬运数据。

这个也可以做为分布式计算的一个框架:生成分区的数据集合,提供可以操作于所有数据分区的方法;如果计算某个分区数据失败时,能单点恢复;为提高性能,尽量做本地化的运算。