Spark学习-一文了解RDD

什么是RDD

RDD(Resilient Distributed Dataset)弹性分布式数据集,RDD从字面理解,分为三个层面:弹性、分布式、数据集

RDD是一种数据集,是Spark对于要处理的数据的抽象,就像Java等高级编程语言中的List、HashMap等集合;

分布式是因为我们通常是以集群形式进行分布式计算,RDD中的数据并非存在一个节点,而是分布于集群各个节点,便于调用各个节点的算力;

RDD的弹性,则涉及较多,如数据分片和调度的弹性、自动进行内存和磁盘数据存储切换的弹性等。

一言以蔽之,RDD是Spark进行数据处理所使用的特殊数据类型。

注意:RDD时只读类型,对RDD的任何操作都不改变RDD本身,只会产生新的RDD。

如何创建RDD

RDD的数据来源有以下几种:

  1. 集合对象,如Array、List、Set、Map等
val arrayRDD: RDD[Int] = sparkContext.parallelize(1 to 10)
  1. 外部数据集,如本地文件、HDFS文件等
# HDFS
val hdfsTxtRDD: RDD[String] = sparkContext.textFile("hdfs://localhost:9000/data/test.txt")

# 本地文件
val localTxtRDD: RDD[String] = sparkSession.sparkContext.textFile("C:/Users/86180/Desktop/*.txt")

外部数据路径可以指定目录,也可以使用通配符。

  1. 通过其他RDD转换
val rddNew: RDD[Int]=arrayRDD.map(i->i*2)

RDD的底层存储原理

Spark学习-一文了解RDD_第1张图片

  1. 一个RDD以Block形式分布在集群各个节点

  2. 集群各个节点都有一个Manager专门管理Block

  3. 当发生RDD出现创建时,从节点的BlockManager会向主节点的BlockManger发起注册

  4. 当RDD不再需要时,主节点会向从节点发送删除指令

  5. 可以看出,主节点的BlockManager只负责管理RDD与Block的关系,并进行操作调度,而不管理Block

RDD的转换和行动操作

针对RDD的操作,主要分为转换操作和行动操作两类,其区别在于是否真正进行计算,转换操作并不执行计算,只有当发起行动操作时才会执行。

了解Java的会发现对RDD的操作,非常类似于文件流Stream的相关操作,如map、filter、count、collect等方法。

转换操作只记录RDD的变换轨迹,类似于制定行动方案,行动操作则相当于执行方案。

常用操作算子

常用的RDD操作主要有以下几个算子:

  1. 映射操作map与flatMap函数 https://blog.csdn.net/weixin_42078760/article/details/106981781

  2. 过滤操作filter与filterNot函数 https://blog.csdn.net/weixin_42078760/article/details/106982020

  3. 规约操作reduce与fold函数 https://blog.csdn.net/weixin_42078760/article/details/106982030

  4. 拆分操作partition、grouped、groupBy和sliding函数 https://blog.csdn.net/weixin_42078760/article/details/106982271

RDD的缓存和持久化

当RDD进行大量迭代运算或需要重复执行某些计算时,如果每次都从头开始,则会造成很大的资源浪费,而且耗时,效率较低,因而可以在适当的时候对运算的中间结果进行缓存或者持久化,以避免重复计算。

缓存级别

RDD的缓存和持久化支持不同级别的存储方式:

  1. MEMORY_ONLY Java对象形式存储于JVM内存,内存不足时,部分数据不再缓存,需要时重新计算

  2. DISK_ONLY 存储于磁盘

  3. MEMORY_AND DISK Java对象形式存储于JVM内存,内存不足时存储于磁盘

  4. MEMORY_ONLY_SER Java对象序列化后存储于JVM内存,内存不足时,部分数据不在缓存

  5. MEMORY_AND_DISK_SER Java对象序列化存储于JVM内存,内存不足时,存储到磁盘

  6. MEMORY_ONLY_2/MEMORY_AND_DISK_2 数据备份到两个节点

  7. OFF_HEAP 序列化后存储于Tachyon,可以减少垃圾回收开销

如何选择缓存和持久化方式

在实际使用中,选择缓存和持久化方式,实际上就是选择内存和CPU的平衡度。

  1. 当RDD数据量较小时,可以使用内存进行缓存,即MEMORY_ONLY

  2. 内存不够但CPU强劲时,可以使用序列化内存缓存,即MEMORY_ONLY_SER

  3. 尽量不要使用磁盘持久化,除非计算过程中会过滤掉大量数据或计算比较麻烦

  4. 如果需要快速失败恢复,则使用备份存储,即MEMORY_ONLY_2/MEMORY_AND_DISK_2

RDD的checkpoint

RDD通过检查点checkpoint进行容错,当设置checkpoint后,并不会立刻执行检查,当执行行动操作时,会在指定目录下创建二进制文件,将RDD持久化存储到磁盘。

何时使用checkpoint

Spark学习-一文了解RDD_第2张图片

当RDD依赖级别非常长,当多个任务使用同一个中间RDD时,且内存无法同时缓存多个中间RDD时,可以将依赖关系切分,进行存储。

简而言之,checkpoint主要用于依赖级别太长时。

RDD依赖关系

Spark学习-一文了解RDD_第3张图片

RDD的操作都是被分片进行计算处理,一个RDD在经过多个操作后产生一个新的RDD,RDD会形成父子依赖关系,RDD的分片partition也会产生依赖关系。这种依赖关系分为两种:窄依赖和宽依赖。

简单来说,窄依赖的每个父级RDD分片最多被一个子RDD分片使用,宽依赖的每个父级RDD会被多个子RDD分片使用。

窄依赖

Spark学习-一文了解RDD_第4张图片

窄依赖分为两种:一对一依赖(OenToOneDependency)和范围依赖(RangeDependency)。

能形成一对一依赖的操作有map、filter等,形成范围依赖的操作有union等。

宽依赖

Spark学习-一文了解RDD_第5张图片
宽依赖涉及shuffle操作,能形成宽依赖关系的操作有groupbykey、reducebykey和join等。

RDD的弹性

1. 自动进行内存和磁盘数据存储的切换

数据优先放在内存中,如果内存不够用,会放到磁盘中。

2. 基于Lineage的高效容错机制

分片数据之间互不影响,每个操作只关联父级操作,若出错,仅需通过数据检查点或记录的数据更新恢复单个分片即可。

3. Task失败后自动重试

默认重试次数为4次。

4. Stage失败后自动重试

默认重试次数为4次。

5. checkpoint和persist既可被动触发,也可主动调用

通过checkpoint方法进行数据检查,通过persist方法进行持久化。

6. DAGScheduler、TASKScheduler和资源管理无关

有向无环图计划(DAG)可以将多Stage任务串联或并行执行,不用保存中间结果,当单节点发生故障时,可用节点接替。

7. 数据分片高度弹性

处理过程中存在数据碎片,如果每个碎片调用一个线程处理,则效率很低,且耗资源,可以通过合并数据分片提升效率。

你可能感兴趣的:(数据开发)