准备知识
要弄清楚Spark的任务调度流程,就必须要清楚RDD、Lineage、DAG和shuffle的相关知识,关于RDD和Lineage,我的这两天文章已经有过相关介绍,感兴趣可以去看一看
【Spark】RDD(Resilient Distributed Dataset)究竟是什么?
【Spark】RDD的依赖关系和缓存相关知识点
接下来说一下DAG的生成和shuffle的过程
DAG
概述
DAG(Directed Acyclic Graph),被称为有向无环图,就是有方向无闭环,是根据RDD之间的依赖关系,也即Lineage形成的。
DAG的生成就是为了划分stage,而stage的划分则是从上往下依次,遇到窄依赖便将其加入到当前stage当中,如果遇到宽依赖就重新开始一个stage,而区别宽窄依赖的依据就是是否发生了shuffle过程,那么stage划分的最终依据就是是否发生shuffle过程,正如下图所示
shuffle
概述
在Spark中,负责shuffle过程的执行、计算和处理的组件主要就是ShuffleManager。在Spark1.2版本前,默认的shuffle计算引擎是 HashShuffleManager,Spark1.2版本后,改成了 SortShuffleManager。
HashShuffleManager有一个重大弊端:会产生大量的中间磁盘文件,进而由大量的磁盘IO操作影响了性能。
SortShuffleManager
SortShuffleManager针对HashShuffleManager的弊端做了改进,设置了两种运行机制:普通运行机制和bypass运行机制。
当shuffle read task的数量小于等于spark.shuffle.sort.bypassMergeThreshold参数的值时(默认为200),就会启用bypass机制。
普通机制
数据会先写到内存大小为5M的缓存中,写满后溢写成为一个个的小文件,并同时进行排序,然后再分批写入到内存缓冲区,进一步写入到磁盘文件中,最后将磁盘文件进行合并,成为一个大文件,并创建对应的索引文件,等待接下来的线程拉取数据
bypass机制
数据不需要经过溢写和排序,直接将数据写入到内存缓冲区,缓冲区写满后溢写到磁盘文件,所有的临时磁盘文件会合并成一个磁盘文件,并创建对应的索引文件,等待拉取
Spark任务调度
流程
一、客户端提交jar包,也就是一个Application
二、Spark会根据Application中的RDD依赖关系,也就是Lineage开始划分DAG
三、划分完成后DAG会被送到DAGScheduler
四、DAGScheduler会根据是否为宽依赖划分Stage,并进一步划分出一个个的taskSet
五、DAGScheduler将划分好的taskSet送到TaskScheduler
六、TaskScheduler接收成功后,会将taskSet划分成为一个个的task,并准备将task发送到Worker中的executor执行
七、与executor进行通信,开始执行task
前六步都是Spark-Driver负责,所以一般推荐使用Cluster模式,将Driver运行在Worker中