Spark调度管理

   速度通常是衡量大数据处理系统性能的一个重要指标。相对于传统的大数据处理框架MapReduce,Spark的批处理速度比MapReduce快近10倍,内存中的数据分析速度则快近100倍。Spark在运行速度方面的突出表现一方面得益于基于内存的计算,另一方面得益于其优秀的调度管理策略

  在Spark的调度管理系统中,从底层物理资源调度到上层应用,涉及众多概念和相关模块,其中作业调度管理是核心。

一:基本概念

1:Application

基于Spark的应用程序,由一个或多个作业组成。每个应用程序的执行涉及Driver program和集群上的Executors两部分

2:Driver program中包含了启动运行函数main函数和一个SparkContext类型的实例。其中SparkContext实例是Application与Spark集群进行交互的唯一通道,是每一个Application的入口。Driver Program可以运行在任何可以提交作业的节点上(Worker,Master),并不是必须运行在节点上。在实际生产环境中为了减少Master的负担,尽量避免在Master上提交Driver Program。

3:Worker

是Spark集群中任何可以运行Application相关代码的节点。

4:Executor

是Worker上为了某个Application启动的一个进程,该进程负责执行任务并且负责将数据存储在内存或磁盘中。Executor拥有CPU和内存资源,它是资源管理系统能够给予的最小单位。一个Worker节点上可能有多个Executor,但是每个Executor中仅执行一个Application对应的任务。也就是说,不同的Application通过Executor无法共享数据。

5:Task

Task即任务,是被送到Executor上执行的工作单元。RDD中的每个分区都对应相应的Task,而每个Task对应于Executor中的一个线程,这使得系统更加轻量级,Task之间切换的时间延迟更短。

6:Job

Job即作业,是包含多个Task的并行计算,与其Application中的执行操作一一对应,也就是说Application每提交一个执行操作Spark对应生成一个Job

7:Stage

通常执行操作之前会有若干个转换操作,而每个转换操作意味着父RDD到子RDD的转换,因此一个Job中通常涉及多个RDD。将Job中涉及的RDD进行分组,每组称为一个RDD

8:Cluster Manager

是在集群上获取资源的外部服务。若是Standalone模式的Spark集群,Cluster Manager即为Master,若是基于Yarn模式的Spark集群,Cluster Manager即为Resource Manager

二:作业调度流程

                       SparkApplication执行框架


在Spark作业调度系统中,调度的前提是判断多个任务的依赖关系,这些作业任务之间可能存在因果的依赖关系,也就是说有些任务必须先获得执行,然后相关的依赖任务才能执行。

在作业调度的相关类中,最重要的就是DAGSchedulerTaskScheduler。DAGScheduler是基于DAG的调度类,负责将作业拆分成不同阶段的具有依赖关系的多批任务组,在逻辑层面实现对Spark作业调度。TaskScheduler则根据不同的任务需求,负责调度和管理每个任务所需的资源,在物理层面实现对Spark作业的执行。

Spark作业调度流程图


作业的生成与提交

SparkApplication中的核心业务逻辑通常是针对若干RDD的一系列操作。操作可分为执行操作和转换操作两类,其中的转换操作采用了惰性策略,即在实际编译和运行应用程序的过程中与转换操作相关的计算都是延迟执行的。转换操作仅仅生成对应的RDD依赖关系链,记录了RDD之间的业务逻辑。只有当应用程序提交了执行操作,才会触发之前一系列转换操作的真正计算,即触发Spark向集群提交实际作业。

如上图的RDD Object部分所示,Spark Application首先在粗描述粒度层面上明确每个子RDD所对应的父RDD。然后通过一个执行操作生成并提交作业。作业的提交是在RDD的相关操作中隐式地被调用,通常并不需要用户显地提交作业。在SparkContext内部,作业的提交将进一步调用DAGScheduler的作业提交接口。

2:阶段的划分

Spark Application中的执行操作触发了作业的生成,然后将作业提交给DAGScheduler,DAGScheduler最主要功能是计算一个作业中RDD之间的依赖关系,指定调度逻辑。DAGScheduler从RDD依赖关系链末端的RDD出发,逆向遍历整个RDD依赖关系链,一方面明确了SparkApplication中涉及哪些RDD,另一方面从较细的粒度层面上分析父RDD分区与子RDD分区之间的关系,确定前后相邻RDD之间的依赖关系,从而得到一个作业对应的DAG,图中的顶点是RDD,边是转换操作导致的依赖关系。DAGScheduler根据RDD之间的依赖关系将DAG图划分为若干个Stage,划分的主要依据是ShuffleDependency,划分原则是将宽依赖关系间的RDD划分在不同阶段中,而窄依赖关系间的RDD则划分在同一阶段中。

DAGScheduler是一个DAG划分成若干个子图,每个子图对应一个Stage,每个Stage中包含了若干了RDD,而每个RDD又由若干个分区组成,其中每个分区上的数据与计算又对应着Task。所以一个Stage可视为一组Task,即Taskset。Taskset中是一组相关的,无需进行Shuffle操作的Task。

3:调度阶段的提交

DAGScheduler是一个面向Stage的调度器,其调度的基本单位是Stage。每个Stage对应一个Taskset,因此DAGScheduler是以Taskset的形式向TaskScheduler提交每个Stage。

在DAGScheduler划分出的若干个Stage中,执行操作处理的RDD所在的Stage称为FinalStage。DAGScheduler进一步从这个FinalStage生成一个作业实例,这两者的关系进一步存储在映射表中,用于在该调度阶段全部完成时做一些后续处理,如报告状态、清理作业相关数据等。

DAGScheduler在具体提交一个Stage时,首先判断该Stage依赖的所有父Stage的结果是否可用,如果都可用,则提交当前Stage;如果存在某个父Stage的结果不可用,则尝试再次提交不可用的Stage。在提交过程中,因依赖的Stage的结果不可用而没有提交成功的Stage,都被放入一个等待列中,等待被提交。

4:任务的提交与执行

DAGScheduler将划分出的Stage以Taskset的形式提交给TaskScheduler。一个TaskScheduler只为一个SparkContext服务。TaskScheduler处理作业的粒度更加精细,它面向Taskset中的每一个Task,以Task作为调度的基本单元。

提交后的每个Taskset会触发TaskScheduler构建一个TaskSetManager的实例来管理这个Taskset的生命周期。TaskSetManager结合数据的存放位置,以最小化通信开销为原则,为每个Task选择运行的节点。如果某个Task需要处理一个已缓存的分区,则直接将任务分配至拥有这个分区的节点。如果需要处理的分区位于多个可能的位置(例如,由HDFS的数据存放位置决定),则将任务分配给这一组节点。Task是Spark应用中执行的最小单元。TaskScheduler借助于Cluster Manager为每一个Task的执行申请系统资源,并在WorkerNode上创建Executor执行Task。

此外,TaskSetManager会追踪和监视每个Task的运行情况,如果一个Task被提交了4次(默认)都没有执行成功,则就认为 该Task执行失败,此时TaskSetManager进行容错处理。

猜你喜欢

转载自blog.csdn.net/mmake1994/article/details/79798436