一.理解RDD 是什么
RDD的全称是:Resilient Distributed Dataset (弹性分布式数据集),它有几个关键的特性:
- RDD是只读的,表示它的不可变性。可以并行的操作分区集合上的所有元素。
怎么做到的呢?我们可以从RDD的内部实现来进行了解。
每个RDD的内部,有5个主要特性:
- 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一起来完成分布式计算,一个是提供数据,一个是提供操作于所有数据的执行运算的能力。
最后,两个可选的特性,一个是可以方便做K-V的划分分区,另一个是优化我们的本地化计算的能力。其中,以能够提供本地化计算的标准,来评价一个组件与spark接合的是否完美。比如HDFS上面的parquet文件,可以完美的做到本地化;而像HBase就不能(目前到spark 2.3.0版本还未能实现),本地化的运算,是分布式计算的根本,即搬运的是函数,而不搬运数据。
这个也可以做为分布式计算的一个框架:生成分区的数据集合,提供可以操作于所有数据分区的方法;如果计算某个分区数据失败时,能单点恢复;为提高性能,尽量做本地化的运算。