这是我参与「第四届青训营 」笔记创作活动的第 9 天
之前我们简单介绍了Spark框架,由此我们知道Spark的生态组件主要有以下几种:Spark Core、 Spark SQL、 Spark Structured Streaming、在各种Cluster Manager运行(独立调度器、Yarn、Mesos、Kubernetes)、 MLlib、 GraphX。
本篇笔记我们主要讲解下Spark Core,我们需要认识spark的核心概念RDD,RDD两种算子处理过程,理解RDD依赖,学习RDD在Spark中的执行流程。
1. RDD概述
1.1 什么是RDD
RDD(Resilient Distributed Dataset) 叫做弹性分布式数据集,是Spark中最基本的数据抽象,是一个容错的、并行的数据结构。
在代码中是一个抽象类,它代表一个弹性的、不可变的、可分区且里面的元素可并行计算的集合。
1.2 RDD特性
* Internally, each RDD is characterized by five main properties:
*
* - 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
* - 0ptionally, a list of preferred locations to compute each split on (e.g. block locations for an HDFS file)
(1)一组分区(Partition),即是数据集的基本组成单位,标记数据是哪个分区的;
protected def getPartitions:Array[Partition]
(2)一个计算每个分区的函数;
def compute(split: Partition, context: TaskContext): Interator[T]
(3)RDD之间的依赖关系;
protected def getDependencies: Seq[Dependency[ ]]=deps
(4)一个Partitioner,即RDD的分片函数;控制分区的数据流向(键值对)
val partitioner : scala.Option[org.apache.spark.Partitioner]
(5)一个列表,存储存取每个Partition的优先位置( preferred location) 。
移动数据不如移动计算,除非资源不够。
protected def getPreferredLocations(split : Partition ) : scala.Seq[String]
2. RDD的两种算子
RDD算子:对任何函数进行某一项操作都可以认为是一个算子,RDD算子是RDD的成员函数
2.1 Transform(转换)算子
根据已有RDD创建新的RDD
2.2 Action(动作)算子
将在数据集上运行计算后的数值返回到驱动程序,从而触发真正的计算。因为转换算子都是懒加载,并不会立即执行。
3. RDD依赖
3.1 窄依赖
窄依赖表示每一个父RDD的Partition最多被子RDD的一个Partition使用(一对一 or 多对一)。 窄依赖可以被比喻为独生子女。
3.2 宽依赖
宽依赖表示同一个父RDD的Partition被多个子RDD的Partition依赖(只能是一对多),会引起Shuffle。 宽依赖可以被比喻为超生。
4. RDD执行过程
划分Stage的整体思路:从后往前推,遇到宽依赖就断开,划分为一个Stage。遇到窄依赖,就将这个RDD加入该Stage中,DAG最后一个阶段会为每个结果的Partition生成一个ResultTask。每个Stage里面的Task数量由最后一个RDD的Partition数量决定,其余的阶段会生成ShuffleMapTask。
- 当RDD对象创建后,SparkContext会根据RDD对象构建DAG有向无环图,然后将Task提交给DAGScheduler。
- DAGScheduler根据ShuffleDependency将DAG划分为不同的Stage,为每个Stage生成TaskSet任务集合,并以TaskSet为单位提交给TaskScheduler。
- TaskScheduler根据调度算法(FIFO/FAIR)对多个TaskSet进行调度,并通过集群中的资源管理器(Standalone模式下是Master,Yarn模式下是ResourceManager)把Task调度(locality)到集群中Worker的Executor,Executor由SchedulerBackend提供。