这是我参与「第四届青训营 」笔记创作活动的第2天
1. Spark简介
1.1 What is Apache Spark™?
Apache Spark™ is a multi-language engine for executing data engineering, data science, and machine learning on single-node machines or clusters.
Apache Spark™ 是一个多语言引擎,用于在单节点机器或集群上执行数据工程、数据科学和机器学习。
1.2 Spark生态和特点
- 统一引擎、支持多种分布式场景
- 多语言支持(java/scala/python)
- 可读写丰富数据源(Text/Parquet/ORC/JSON/CSV/JDBC/自定义数据源)
- 丰富灵活的API算子
- 支持K8s/Yarn/Mesos资源调度
1.3 Spark运行架构 & 部署方式
- Spark Local Mode (本地测试/单进程多线程模式)
spark-sql --master local[*] ... - Spark Standalone Mode (启动Standalone集群Master/Worker)
spark-sql --master spark://${master_ip}:${port} ... - Spark on YARN/K8s (依赖外部资源调度器)
spark-ssql --master yarn ...spark-sql --master k8s://https//<k8s-apiserver-host><k8s-apiserver-port> ...
2. SparkCore
2.1 RDD
The main abstraction Spark provides is a resilient distributed dataset (RDD), which is a collection of elements partitioned across the nodes of the cluster that can be operated on in parallel.
Spark 提供的主要抽象是弹性分布式数据集(RDD),它是跨集群节点分区的元素集合,可以并行操作。
(1) 创建RDD
- 并行化现有集合
- 引用外部数据源
There are two ways to create RDDs: parallelizing an existing collection in your driver program, or referencing a dataset in an external storage system, such as a shared filesystem, HDFS, HBase, or any data source offering a Hadoop InputFormat.
(2) 描述RDD的5个要素
abstract class RDD{
def compute(split: Partition, context: TaskContext): Iterator[T]
def getPartitions: Array[Partition]
def getDependencies: Seq[Dependency[_]] = deps
def getPreferredLocations(split: Partition): Seq[String] = Nil
val partitioner: Option[Partitioner] = None
}
- compute(): 计算给定的分区
- getPartitions(): 返回 RDD 中的分区集
- getDependencies(): 返回当前RDD如何依赖于父RDD
- preferredLocations(): 按照“移动计算比移动数据便宜”,实现计算数据的本地化
- partitioner: 一个partition默认是使用hashPartitioner
(3) RDD算子
- Transform算子: 生成一个新RDD
- Action算子: 触发Job提交
(4) RDD依赖
- 窄依赖(Narrow\Prune\Range\OneToOne):父RDD的每个partition至多对应一个子RDD
- 宽依赖(ShuffleDependency):父RDD的每个partition都可能对应多个子RDD
(5) RDD执行流程
- Job:RDD Action算子作业提交
- Stage:依据宽依赖(ShuffleDependency)进行划分
- Task:Stage内执行单个 Partition 任务
RDD的执行流程:
RDD.action-->runJob()-->DAGScheduler-->TaskScheduler
(6) DAG Scheduler
根据 ShuffleDependency 切分 Stage ,并按照依赖顺序调度Stage,为每个 Stage 生成并提交 TaskSet 到 TaskScheduler。
根据调度算法对多个TaskSet进行调度。对于调度到的TaskSet会将Task根据Locality调度到相关Executor上执行。
Locality:PROCESS_LOCAL, NODE_LOCAL, RACK_LOCAL, ANY
2.2 内存管理(Memory Management)
Executor内存:
- Storage
- Execution
2.3 Shuffle
- 每个MapTask生成一个Shuffle数据文件和一个index文件
- dataFile中的数据按照partitionID进行排序
- 方便后续ReduceTask能fetch到对应partitionID的数据
Shuffle write的文件被NodeManager中的ESS托管,供后续的ReduceTask进行shuffle fetch。