首页 理论教育 抽象概念RDD的解析及应用

抽象概念RDD的解析及应用

时间:2023-06-25 理论教育 版权反馈
【摘要】:RDD是Spark中最重要的一个抽象概念,为了更容易理解RDD这一抽象概念,这里给出比较通俗的描述。属于RDD元素是键值对这一特定类型的RDD。RDD为一些特定类型的T提供了额外的功能,这部分内容可以参考本书2.3节RDD API的应用案例与解析部分。RDD抽象类的这五个方法对应的源码如下所示:

抽象概念RDD的解析及应用

RDD是弹性分布式数据集的简称,其本身是一个抽象类,其内部实现包括以下五个部分,其中前三个是必备的:

1)getPartitions方法:分区列表(数据块列表)。

2)compute方法:计算每个分片的函数。

3)getDependencies方法:对父RDD的依赖列表。

4)partitioner:Key-Value(键-值)RDD的分区器。

5)getPreferredLocations方法:每个数据分片的预定义地址列表(如HDFS上的数据块的地址)。

其中,前三个用于描述RDD间的Lineage(即血统关系,此概念在后面有专门解释)信息,后两个可用于优化执行。

RDD是Spark中最重要的一个抽象概念,为了更容易理解RDD这一抽象概念,这里给出比较通俗的描述。

1.首先RDD的定义为RDD[T],可以将RDD理解成T实例的一个集合,即RDD中的每条记录都是一个T实例,比如T为String时,RDD就是一组String字符串的集合。(www.xing528.com)

2.对应的分区就是将这一组T实例的集合拆分成多个子集合,这里子集合也就是我们的数据分区。数据以Block,即块方式存储在HDFS上,加载后,在Spark中,子集合实际上对应着分区的概念。分区就是将对应大数据量的T实例集合切(split)成多个小数据量的T实例子集合。这个集合,对应的内部代码其实就是Iterator[T]。

3.用于构建该RDD的父RDD即是该RDD的父依赖,由于可以有多个父依赖的RDD,因此有对应父RDD的一个依赖列表。对于RDD间的依赖关系,首先需要理解一个概念,就是依赖这个概念是通过RDD的分区间的依赖来体现的,通过这个依赖列表,以及该RDD的getPartitions方法,可以知道RDD的各个分区是如何依赖一组父RDD的分区的,比如最简单的映射(map)转换,转换后的RDD(MapPartitionsRDD)各个分区,依赖父RDD的各个分区(分区为一一对应的依赖关系)。也就是转换后RDD各个分区的数据Block,是来自父RDD的对应分区的数据Block。

4.计算每个分片的函数compute,体现了惰性(lazy)计算的特性,比如:MapPartition-sRDD,对应的compute函数记录了该RDD对父依赖的各个分区数据的操作,也就是记录了对MapPartitionsRDD各个分区的输入源数据进行的计算。当其他RDD从MapPartitionsRDD获取数据或要存储到外部存储系统时(有Action触发),就会执行这个计算每个分片的函数compute。因为这里只是记录操作,所以在窄依赖时可以采用pipeline方式,流水线式地进行计算。

这里再补充介绍两点:

1)compute函数是针对分区的数据,所以计算的并行数也就是分区的个数。

2)compute函数是针对分区的数据,可以认为计算的粒度是分区粒度,因此可以认为RDD的计算,某种程度上是粗粒度的。也就是如果使用RDD的compute函数,则大部分API的计算都是针对分区的,而不是针对RDD的T元素。如果需要对RDD的T元素进行更细粒度的处理,可以使用RDD的mapPartitions操作,直接处理分区的数据Iterator[T]。

5.Key-Value RDD,其实就是T类型为Key-Value对的类型。属于RDD元素是键值对这一特定类型的RDD。RDD为一些特定类型的T提供了额外的功能,这部分内容可以参考本书2.3节RDD API的应用案例与解析部分。

RDD抽象类的这五个方法对应的源码如下所示:

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈