spark封神之路(4)-RDD详解

3.1 RDD概述

3.1.1 RDD特点

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

  • 弹性
    • 容错的弹性:数据丢失可以自动恢复;
    • 存储的弹性:内存与磁盘的自动切换;
    • 计算的弹性:计算出错重试机制;·
    • 分片的弹性:可根据需要重新分片。
  • 分布式:数据存储在集群不同节点上/计算分布式
  • 数据集: RDD封装了计算逻辑,并不保存数据
  • 数据抽象: RDD是一个抽象类,需要子类具体实现
  • 不可变: RDD封装了计算逻辑,是不可以改变的,想要改变,只能产生新的RDD,在新的RDD里面封装计算逻辑
  • 可分区、并行计算

3.1.2 RDD属性

*  - 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)
  • 分区列表

RDD数据结构中存在分区列表,用于执行任务时并行计算,是实现分布式计算的重要属性。

  多个分区. 分区可以看成是数据集的基本组成单位.

  对于 RDD 来说, 每个分区都会被一个计算任务处理, 并决定了并行计算的粒度.

  用户可以在创建 RDD 时指定 RDD 的分区数, 如果没有指定, 那么就会采用默认值. 默认值就是程序所分配到的 CPU Coure 的数目.

  每个分配的存储是由BlockManager 实现的. 每个分区都会被逻辑映射成 BlockManager 的一个 Block, 而这个 Block 会被一个 Task 负责计算.

/**

  * Implemented by subclasses to return the set of partitions in this RDD. This method will only

  * be called once, so it is safe to implement a time-consuming computation in it.

  *

扫描二维码关注公众号,回复: 13161459 查看本文章

  * The partitions in this array must satisfy the following property:

  *   `rdd.partitions.zipWithIndex.forall { case (partition, index) => partition.index == index }`

  */

 protected def getPartitions: Array[Partition]

  • 分区计算函数

Spark在计算时,是使用分区函数对每一个分区进行计算

 /**

  * :: DeveloperApi ::

  * Implemented by subclasses to compute a given partition.

  */

 @DeveloperApi

 def compute(split: Partition, context: TaskContext): Iterator[T]

  • 与其他RDD之间的依赖

RDD 的每次转换都会生成一个新的 RDD, 所以 RDD 之间会形成类似于流水线一样的前后依赖关系. 在部分分区数据丢失时, Spark 可以通过这个依赖关系重新计算丢失的分区数据, 而不是对 RDD 的所有分区进行重新计算.

 /**

  * Implemented by subclasses to return how this RDD depends on parent RDDs. This method will only

  * be called once, so it is safe to implement a time-consuming computation in it.

  */

 protected def getDependencies: Seq[Dependency[_]] = deps

  • 对存储键值对的 RDD, 还有一个可选的分区器.

只有对于 key-value的 RDD, 才会有 Partitioner, 非key-value的 RDD 的 Partitioner 的值是 None. Partitiner 不但决定了 RDD 的本区数量, 也决定了 parent RDD Shuffle 输出时的分区数量.

/** Optionally overridden by subclasses to specify how they are partitioned. */

 @transient val partitioner: Option[Partitioner] = None

  • 位置优先

存储每个切片优先(preferred location)位置的列表. 比如对于一个 HDFS 文件来说, 这个列表保存的就是每个 Partition 所在文件块的位置. 按照“移动数据不如移动计算”的理念, Spark 在进行任务调度的时候, 会尽可能地将计算任务分配到其所要处理数据块的存储位置.

/**

  * Optionally overridden by subclasses to specify placement preferences.

  */

 protected def getPreferredLocations(split: Partition): Seq[String] = Nil

3.1.3 RDD 执行原理

从计算的角度来讲,数据处理过程中需要计算资源(内存& CPU)和计算模型(逻辑)。执行时,需要将计算资源和计算模型进行协调和整合。

Spark框架在执行时,先申请资源,然后将应用程序的数据处理逻辑分解成一个一个的计算任务。然后将任务发到已经分配资源的计算节点上,按照指定的计算模型进行数据计算。最后得到计算结果。

RDD是Spark框架中用于数据处理的核心模型,接下来我们看看,在Yarn环境中,RDD的工作原理:

1)  启动yarn资源调度平台

2) spark申请资创建调度节点和计算节点

3) Spark框架根据需求将计算逻辑根据分区划分成不同的任务

4)调度节点将任务根据计算节点状态发送到对应的计算节点进行计算

RDD在整个流程中主要用于将逻辑进行封装,并生成Task 发送给Executor节点执行计算,接下来我们就一起看看Spark框架中RDD是具体是如何进行数据处理的。

 

猜你喜欢

转载自blog.csdn.net/qq_37933018/article/details/117699302