————Spark技术内幕读书笔记———— |
本书的三个核心:
Scheduler任务调度充分体现了与MapReduce完全不同的设计思想。
MapReduce把计算拆分为Map阶段与Reduce阶段,一个Job两阶段完成就完成了,采用的是分治思想,对于复杂的计算时可能需要多次串联多个MR生成多个Job来完成。
而Spark则不同,采用的是内存迭代式计算,也就是一个Job它可以分为n个阶段(Stage),Stage划分的依据是Shuffle,无论多复杂的计算大部分都可以在多个Job中完成所有的Stage,且Shuffle时除非内存不足时才会Spill写磁盘,否则子Stage的RDD会根据Shuffle的算法从父Stage的Partition中拿到属于自己Partition的数据,生成新的RDD,所有迭代计算都是在内存中完成,效率就比较高。
调度系统——上面基于内存的迭代式计算主要就依赖于DAGScheduler与TaskScheduler来分配计算资源!
Spark对于DAG与Task的实现以及不同执行阶段的划分和任务的提交执行,充分体现了其设计的优雅与高效!
spark集群中Driver、Cluster Manager、Worker、Executor之间在的关系图:
————第四章 Scheduler模块详解———— |
任务调度整体架构
将用户提交的计算任务按照DAG划分不同的阶段的计算任务提交到集群进行最终的计算
RDD Objects:从RDDS中构建DAG。实际代码中创建的RDD,是DAG的基本元素,Spark提供了丰富的Transformation和Action算子来对它进行操作。
DAGScheduler:对DAG进行任务切分,生成TaskSet。分析用户提交的应用、并根据计算任务的依赖关系建立 DAG,然后将DAG划分为不同的Stage阶段,其中每个Stage由可以并发进行执行的一组Task任务构成,所有Task的执行逻辑完全相同,只是处理的数据不一样。DAG无论在任何部署方式下都是相同的。在DAGScheduler将Task任务划分完成后,将Task组提交给TaskScheduler。
TaskScheduler:启动任务并调度任务(就近原则)。收到任务集后,TaskScheduler通过Cluster Manager在集群的某个Worker的Executor上启动任务。任务完成后将结果保存到指定地方或回传到Driver。
TaskScheduler为创建它的SparkContext调度任务,从DAGScheduler接收不同Stage的任务,并向集群提交这些任务,并为执行得特别慢的任务启动备份任务。
TaskScheduler的具体实现交给TaskSchedulerImpl实现。
TaskSchedulerImpl会在以下4种情况调用SchedulerBackend的reviveOffers为其分配计算资源:
- 有新任务提交时
- 有任务执行失败时
- 计算节点Executor不可用时
- 某些任务运行过慢需要为其重新分配资源时。
Executor:任务执行
最核心的三个类:
- org.apache.spark.scheduler.DAGScheduler
- org.apache.spark.scheduler.SchedulerBackend
- org.apache.spark.scheduler.TaskScheduler
SchedulerBackend:分配当前可用计算资源
为Task分配Executor计算资源,并在所分配的Executor上启动Task,完成计算的调度过程。reviveOffers是具体实现的方法。
每个