Spark学习(三):核心模块之RDD详解

1. Spark核心模块整体简介

(1)Spark的关键运算组件图:

Spark学习(三):核心模块之RDD详解

(2)总结:

Spark的核心组件总结包括RDD、Scheduler、Storage、Shuffle四部分:

1)RDD是Spark最核心最精髓的部分,spark将所有数据都抽象成RDD。

2)Scheduler是Spark的调度机制,分为DAGScheduler和TaskScheduler。

3)Storage模块主要管理缓存后的RDD、shuffle中间结果数据和broadcast数据

4)Shuffle分为Hash方式和Sort方式,两种方式的shuffle中间数据都写本地盘

2. 核心模块——RDD整体介绍

(1)RDD的概念:

1)RDD是Spark的基石,也是Spark的灵魂。

2)RDD是弹性分布式数据集,是只读的分区记录集合。

(2)每个RDD有5个主要的属性:

1)一组分片(Partition):数据集的最基本组成单位

2)一个计算每个分片的函数:对于给定的数据集,需要做哪些计算

3)依赖(Dependencies):RDD的依赖关系,描述了RDD之间的lineage

4)preferredLocations(可选):对于data partition的位置偏好

5)partitioner(可选) -- 对于计算出来的数据结果如何分发

(3)RDD的举例1:

rdd1= sparkContext.textFile( “hdfs://…”)

rdd1是一个MappedRDD,该RDD是从外部文件创建的。

可以传入分片个数参数,否则采用defaultMinPartitions。

(4)RDD的举例2:

rdd2= rdd1.filter(_.startsWith( “ERROR”))

rdd2也是一个FilteredRDD,是从rdd1这个RDD衍生(即计算)得到的。

rdd1是rdd2的父节点,即rdd2依赖rdd1。

filter是RDD的操作,即每个分片需要计算的函数。

3. 核心模块——RDD操作

(1)RDD的操作工分为两类:转换transformations和动作actions

1)转换transformations

从现有的数据集创建一个新的数据集即数据集中的内容会发生更改,由数据集A转换成为数据集B

2)动作actions

在数据集上运行计算后,返回一个值给驱动程序。 即数据集中的内容会被归约为一个具体的数值(Scala标量、集合类型的数据或存储)。

(2)具体的RDD方法举例如图:

Spark学习(三):核心模块之RDD详解

4. 核心模块——RDD的持久化

(1)RDD持久化的时机:

1)默认情况下,每一个转换过的RDD都会在它之上执行一个动作时被重新计算。

2)如果rdd只被使用一次或者很少次,不需要持久化。如果rdd被重复使用或者计算其代价很高,才考虑持久化。另外,shuffle后生成的rdd尽量持久化,因为shuffle代价太高。

(2)RDD持久化的效果:

1RDD被缓存后,Spark将会在集群中,保存相关元数据,下次查询这个RDD时,它将能更快速访问,不需要计算。

2)如果持久化无谓的RDD,会浪费内存(或硬盘)空间,反而降低系统整体性能

(3)RDD持久化的方法:

1)使用 persist方法(或者cache方法),持久化一个RDD在内存或磁盘中。

2)cache()过程是将RDD persist在内存里,persist()操作可以为RDD指定StorageLevel。

(4)RDD的存储级别StorageLevel

Spark学习(三):核心模块之RDD详解

5. 核心模块——RDD依赖关系

(1)RDD之间存在依赖的原因:

1)RDD只能基于在稳定物理存储中的数据集和其他已有的RDD上执行确定性操作来创建。

2)能从其他RDD通过确定操作创建新的RDD的原因是RDD含有从其他RDD衍生(即计算)出本RDD的相关信息(即Lineage)

(2)RDD依赖的分类:

Dependency代表了RDD之间的依赖关系,即血缘(Lineage),分为窄依赖和宽依赖。

(3)窄依赖和宽依赖图形表示:

Spark学习(三):核心模块之RDD详解

(4)依赖详解

窄依赖:

•一个父RDD最多被一个子RDD用

•常见的操作:map、filter、union等;

宽依赖:

•指子RDD的分区依赖于父RDD的所有分区,这是因为shuffle类操作要求所有父分区可用。

•常见的操作:比如groupByKey、reduceByKey、 sort、partitionBy等;

(5)基于RDD的依赖关系,spark的任务阶段划分原则:

根据RDD依赖关系的不同,Spark将每一个job分为不同的stage,stage之间的依赖关系形成了DAG图。具体来讲就是:

1)窄依赖Spark将其尽量划分在同一个stage中,因为它们可以进行流水线计算。

2)宽依赖往往意味着shuffle操作,这也是Spark划分stage的主要边界。

(6)阶段stage划分的示例图:

Spark学习(三):核心模块之RDD详解

(7)针对示例图的解释:

1)一个Stage的开始就是从外部存储或者shuffle结果中读取数据;一个Stage的结束就是发生shuffle或者生成结果时。

2)由于rdd F是rdd G的宽依赖,所以将F与G分别划分到不同的stage,但是B是G的窄依赖(B的每个分区只被使用一次),所以B与G还保持在一个stage。

3)由于rdd A是rdd B的宽依赖,所以A和B划分在不同的stage

4)在图中Stage2中,从map到union都是窄依赖,在一个stage,这两步操作可以形成一个流水线操作,通过map操作生成的partition可以不用等待整个RDD计算结束,而是继续进行union操作,这样大大提高了计算的效率。

6. 核心模块——RDD的容错关系

如果transformation操作中间发生计算失败:

1)运算是窄依赖

只要把丢失的父RDD分区重算即可,跟其他节点没有依赖,这样可以大大加快场景恢复的开销。

2)运算是宽依赖

需要父RDD的所有分区都存在, 重算代价就较高

3)增加检查点

当Lineage特别长时或者有宽依赖时,主动调用 checkpoint把当前数据写入稳定存储,作为检查点

相关推荐