Spark原理与实践 | 青训营笔记

119 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的第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 任务

image.png

RDD的执行流程:

RDD.action-->runJob()-->DAGScheduler-->TaskScheduler

image.png

(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。

image.png