RDD,Resilient Distributed Object,弹性分布式数据集,是Spark牛逼的基石。
RDD是什么?
Spark使用RDD类对RDD进行了抽象,如下是,RDD类的scaladoc,
A Resilient Distributed Dataset (RDD), the basic abstraction in Spark. Represents an immutable, partitioned collection of elements that can be operated on in parallel. This class contains the basic operations available on all RDDs, such as map, filter, and persist. In addition, org.apache.spark.rdd.PairRDDFunctions contains operations available only on RDDs of key-value pairs, such as groupByKey and join; org.apache.spark.rdd.DoubleRDDFunctions contains operations available only on RDDs of Doubles; and org.apache.spark.rdd.SequenceFileRDDFunctions contains operations available on RDDs that can be saved as SequenceFiles. These operations are automatically available on any RDD of the right type (e.g. RDD[(Int, Int)] through implicit conversions when you import org.apache.spark.SparkContext._.
Internally, each RDD is characterized by five main properties:
A list of partitions
A function for computing each split
A list of dependencies on other RDDs
Optionally, a Partitioner for key-value RDDs (e.g. to say that the RDD is hash-partitioned)
Optionally, a list of preferred locations to compute each split on (e.g. block locations for an HDFS file)
All of the scheduling and execution in Spark is done based on these methods, allowing each RDD to implement its own way of computing itself. Indeed, users can implement custom RDDs (e.g. for reading data from a new storage system) by overriding these functions. Please refer to the Spark paper for more details on RDD internals.
对它进行翻译:
1. RDD,全称Resilient Distribute Dataset,即弹性分布式数据集,是Spark对于计算数据的基本抽象。RDD代表了一个不可变的且已经分区了的数据集合,这些数据由于RDD的不可变性而使得非常适合并行处理。
2. RDD是一个抽象类,它其中定义了一些所有的RDD都会用到的方法,比如map、filter和persist。
- org.apache.spark.rdd.PairRDDFunctions定义了数据为键值对的RDD才可用的方法,比如groupByKey和join
- org.apache.spark.rdd.DoubleRDDFunctions定义了数据为双精度浮点型的RDD才可用的方法
- org.apache.spark.rdd.SequenceFileRDDFunctions定义了数据可以序列化为SequenceFiles的RDD才可用的方法
这些特定于具体类型的方法对这种类型的RDD是自动可用的,Spark是通过隐式类型转换实现的,要使用Spark的隐式类型转换功能,则需要再代码中加入一行import语句:import org.apache.spark.SparkContext._
3. 在RDD的内部,每个RDD有五个主要的特性:
- RDD是一系列的分区,即数据按照某个分区规则进行了分区
- 一个对每个分片(split,不是partition,partition翻译成分区 纠正:这里的split可以理解为partition)指定计算的方法(是不是就是RDD.compute方法 答:不是,这里的计算方法其实就是作用于RDD上的如map,filter等这样的方法,作用于RDD本意上是为了作用于所有的Partition,Partition才是计算的的基本单位)
- RDD之间是有依赖关系的,RDD中定义了它对其它RDD(一个或者多个)的依赖,比如对RDD A做map操作得到RDD B,对RDD B做filter得到RDD C,那么A是B的父RDD,B依赖于A;那么B是C的父RDD,C依赖于B;
- 可选择地,对于Key/Value RDD,可以有一个实现了分区规则的Partitioner(比如说,一个RDD是基于哈希分区的,Hash-Partitioned)
- 可选择地,在计算每个分片(split)时,分片要包含的数据的首选位置(一个或者多个),比如,HDFS文件的块位置
4. Spark中,所有任务的调度和执行都依赖于这些方法,这些方法使每个RDD可以使用它们自己的方式方法来计算它们自己。当然,Spark也允许用户通过重写这些方法以实现自定义的RDD来满足需求(比如实现对某种新型的存储系统读写操作)
总结RDD特性:
- 它是不变的数据结构存储
- 它是支持跨集群的分布式数据结构
- 可以根据数据记录的key对结构进行分区
- 提供了粗粒度的操作,且这些操作都支持分区
- 它将数据存储在内存中,从而提供了低延迟性
- 如下红字于2015.1.5更新
- RDD will be rebuilt on failure based on lineage and checkpoint
- There are different storage level for RDD(意思是RDD可以存放于不同的存储介质中,称为Storage Level)。RDD在内存吃紧时,会转储到磁盘中
RDD vs Partition(2015.1.5)
一个RDD由多个Partition组成,比如一个RDD由10个Partition组成,在Spark中,操作的粒度是Partition,所以对RDD调用map,filter方法,最终是对RDD中的partition执行map和filter计算。在Spark中,一个Partition对应一个Task。
RDD vs RealDataSource(2015.1.5)
RDD是Spark对数据集的一种抽象,在内存充足的情况下,Spark会把多种来源的数据源记载到内存中,构造成RDD。对RDD的操作分成两类,一个是Transform,一个是Action。Transformation类型的操作不会真正的去做操作对应的事情(只是调用了,但是尚未执行,这是一种延迟策略,比如对RDD A做了map得到B,并没有真正的对A中的数据集或者每个Partition实施map操作),RDD只有在Action类型的操作彩会触发真正的执行(启动Job)
RDD五个特性对应的方法
- compute是一个抽象方法,用于对一个分区进行计算,返回类型是一个可遍历的集合(T是泛型,实例化RDD时需要提供)
- getPartitions是一个抽象方法,用于返回这个RDD包含的分区列表(返回值是Array[Partition]),这个方法可以进行耗时的计算,因为只会调用一次
- getDependencies是具体方法,用于返回这个RDD所依赖的其它RDD列表,这个方法可以进行耗时的计算,因为只会调用一次
- getPreferredLocations是具体昂发,用于计算该分区中的数据的首选位置
- partitioner:是一个属性,可以被继承,以实现对RDD中所有数据进行分区的规则
RDD两类操作
RDD操作分为Transform和Action两类,如下图所示,这幅图来自于RDD的论文
RDD cache(2015.1.5)
对RDD执行cache操作,产生什么样的影响?提出这个问题的原因是想到一个问题,RDD什么时间把数据源上(比如HDFS)的数据加载到RDD中了?
HadoopRDD详解
本来想看看HadoopRDD如何体现上面关于RDD的五个特性,无奈有两方面的原因使这个计划必须暂时搁置
1. Hadoop的工作机制不甚了解
2. Scala语言不熟悉
等到春暖花开之时,再研究它