什么是RDD?带你快速了解Spark中RDD的概念!

        看了前面的几篇Spark博客,相信大家对于Spark的基本概念以及不同模式下的环境部署问题已经搞明白了。但其中,我们曾提到过Spark程序的核心,也就是弹性分布式数据集(RDD)。但到底什么是RDD,它是做什么用的呢?本篇博客,我们就来详细讨论它们的使用情况。
在这里插入图片描述


RDD概述

1.什么是RDD

        RDD(Resilient Distributed Dataset)叫做分布式数据集,是Spark中最基本的数据抽象。代码中是一个抽象类,它代表一个不可变、可分区、里面的元素可并行计算的集合。

2.RDD的属性

在这里插入图片描述
- 1) A list of partitions

        一个分区列表,一个rdd有多个分区,后期spark任务计算是以分区为单位,一个分区就对应上一个task线程。 通过val rdd1=sc.textFile(文件) 如果这个文件大小的block个数小于等于2,它产生的rdd的分区数就是2 如果这个文件大小的block个数大于2,它产生的rdd的分区数跟文件的block相同。

- 2)A function for computing each split

        由一个函数计算每一个分片 比如: rdd2=rdd1.map(x=>(x,1)) ,这里指的就是每个单词计为1的函数。

- 3)A list of dependencies on other RDDs

        一个rdd会依赖于其他多个rdd,这里就涉及到rdd与rdd之间的依赖关系,后期spark任务的容错机制就是根据这个特性而来。 比如: rdd2=rdd1.map(x=>(x,1)) rdd2的结果是通过rdd1调用了map方法生成,那么rdd2就依赖于rdd1的结果 对其他RDD的依赖列表,依赖还具体分为宽依赖和窄依赖,但并不是所有的RDD都有依赖。

- 4)Optionally, a Partitioner for key-value RDDs (e.g. to say that the RDD is hash-partitioned)

        (可选项) 对于kv类型的rdd才会有分区函数(必须要产生shuffle),对于不是kv类型的rdd分区函数是None。 分区函数的作用:它是决定了原始rdd的数据会流入到下面rdd的哪些分区中。 spark的分区函数有2种:第一种hashPartitioner(默认值), 通过 key.hashcode % 分区数=分区号 第二种RangePartitioner,是基于一定的范围进行分区。

- 5)Optionally, a list of preferred locations to compute each split on (e.g. block locations for an HDFS file)

        (可选项) 一组最优的数据块的位置,这里涉及到数据的本地性和数据位置最优 spark后期在进行任务调度的时候,会优先考虑存有数据的worker节点来进行任务的计算。大大减少数据的网络传输,提升性能。这里就运用到了大数据中移动数据不如移动计算理念

3.RDD特点

        RDD表示只读的分区的数据集,对RDD进行改动,只能通过RDD的转换操作,由一个RDD得到一个新的RDD,新的RDD包含了从其他RDD衍生所必需的信息。RDDs之间存在依赖,RDD的执行是按照血缘关系延时计算的。如果血缘关系较长,可以通过持久化RDD来切断血缘关系。

3.1 分区

        RDD逻辑上是分区的,每个分区的数据是抽象存在的,计算的时候会通过一个compute函数得到每个分区的数据。如果RDD是通过已有的文件系统构建,则compute函数是读取指定文件系统中的数据,如果RDD是通过其他RDD转换而来,则compute函数是执行转换逻辑将其他RDD的数据进行转换。
在这里插入图片描述

3.2 只读

        如下图所示,RDD是只读的,要想改变RDD中的数据,只能在现有的RDD基础上创建新的RDD。

在这里插入图片描述
        由一个RDD转换到另一个RDD,可以通过丰富的操作算子实现,不再像MapReduce那样只能写map和reduce了,如下图所示。
在这里插入图片描述
        RDD的操作算子包括两类,一类叫做transformations转化,它是用来将RDD进行转化,构建RDD的血缘关系;另一类叫做actions动作,它是用来触发RDD的计算,得到RDD的相关计算结果或者将RDD保存的文件系统中。

3.依赖

        RDDs通过操作算子进行转换,转换得到的新RDD包含了从其他RDDs衍生所必需的信息,RDDs之间维护着这种血缘关系,也称之为依赖。如下图所示,依赖包括两种,一种是窄依赖,RDDs之间分区是一一对应的,另一种是宽依赖,下游RDD的每个分区与上游RDD(也称之为父RDD)的每个分区都有关,是多对多的关系。
在这里插入图片描述

4.缓存

        如果在应用程序中多次使用同一个RDD,可以将该RDD缓存起来,该RDD只有在第一次计算的时候会根据血缘关系得到分区的数据,在后续其他地方用到该RDD的时候,会直接从缓存处取而不用再根据血缘关系计算,这样就加速后期的重用。如下图所示,RDD-1经过一系列的转换后得到RDD-n并保存到hdfs,RDD-1在这一过程中会有个中间结果,如果将其缓存到内存,那么在随后的RDD-1转换到RDD-m这一过程中,就不会计算其之前的RDD-0了。

在这里插入图片描述

5.CheckPoint

        虽然RDD的血缘关系天然地可以实现容错,当RDD的某个分区数据失败或丢失,可以通过血缘关系重建。但是对于长时间迭代型应用来说,随着迭代的进行,RDDs之间的血缘关系会越来越长,一旦在后续迭代过程中出错,则需要通过非常长的血缘关系去重建,势必影响性能。为此,RDD支持checkpoint将数据保存到持久化的存储中,这样就可以切断之前的血缘关系,因为checkpoint后的RDD不需要知道它的父RDDs了,它可以从checkpoint处拿到数据。
        
        


        好了,本次的分享就到这里,受益的小伙伴或对大数据技术感兴趣的朋友可以点个赞哟,下一篇将为大家带来RDD编程,敬请期待!!!
        
        
        
在这里插入图片描述

发布了202 篇原创文章 · 获赞 1621 · 访问量 41万+

猜你喜欢

转载自blog.csdn.net/weixin_44318830/article/details/104456093