Spark学习笔记(二)| Spark任务调度机制

文章目录

  • 1. Spark任务调度概述
  • 2. Spark通信机制
  • 3. 任务调度过程
    • 3.1 Spark Stage 级调度
    • 3.2 Spark Task 级调度
      • 3.2.1 调度策略
      • 3.2.2 本地化调度
      • 3.2.3 失败重试与黑名单机制

1. Spark任务调度概述

当Driver任务启动之后,Driver则会根据用户程序逻辑准备任务,并根据Executor资源情况逐步分发任务。
一个Spark应用程序包括Job、Stage以及Task三个概念:

  • Job: 以Action算子为界,遇到一个Action算子就触发一个Job;
  • Stage: 是Job的子集,以RDD宽依赖(即Shuffle)为界,遇到Shuffle做一次划分;
  • Task: 是Stage的子集,以并行度(分区数)来衡量,分区数是多少,则有多少Task

2. Spark通信机制

(待补充)

3. 任务调度过程

Spark任务调度分为两种粒度:

  • Stage级的调度
  • Task级的调度

DAGScheduler: 负责Stage级的调度,将Job切分成若干Stage,并将每个Stage打包成TaskSet交给TaskScheduler调度。
TaskScheduler: 负责Task级的调度,将TaskSet按照指定的调度策略分发到Executor上执行,调度过程中SchedulerBackend负责提供可用资源(SchedulerBackend有多种实现,对应不同的资源管理系统)

Spark RDD通过其 Transactions(转换) 操作,形成RDD血缘关系图(DAG),最后通过Action(行动)的调用,触发Job并调度执行。

下图描述 Spark-On-YARN模式下在任务调度期间,ApplicationMaster、Driver、Executor内部模块的交互过程
Spark学习笔记(二)| Spark任务调度机制_第1张图片

3.1 Spark Stage 级调度

Spark的任务调度是从DAG切割开始,主要是由DAGScheduler来完成。当遇到一个Action算子操作后就会触发一个Job的计算,并交给DAGScheduler来提交,下图是涉及到Job提交的相关方法调用流程图(按箭头顺序):
Spark学习笔记(二)| Spark任务调度机制_第2张图片

  • 一个Stage是否被提交,需要判断它的父Stage是否执行,只有在父Stage执行完毕才能提交当前Stage;如果当前Stage没有父Stage,则从当前Stage开始提交。

3.2 Spark Task 级调度

Spark Task的调度是由TaskScheduler来完成,前面的处理流程中,DAGScheduler将Stage打包到 TaskSet 交给TaskScheduler, TaskScheduler会将 TaskSet 封装为TaskSetManager加入到调度队列中,TaskSetManager结构如下所示:
Spark学习笔记(二)| Spark任务调度机制_第3张图片

  • TaskSetManager负责监控管理同一个Stage中的Tasks,TaskScheduler就是以TaskSetManager为单元来调度任务

如图所示

  • TaskScheduler初始化后会启动SchedulerBackend,它负责跟外界进行通讯,接收Executor的注册信息,并维护Executor的状态。同时它会定期的去询问TaskScheduler,而TaskScheduler在被询问时,会从调度队列中按照指定的调度策略选择TaskSetManager去调度执行,Task调度流程大致如下图所示:
    Spark学习笔记(二)| Spark任务调度机制_第4张图片
  1. 第一步是TaskScheduler将接收到的TaskSet封装为TaskSetManager之后放入池子中
  2. 第二步就是从任务队列中按照相应的调度策略取出来在SchedulerBackend给过来的Executor上运行

3.2.1 调度策略

TaskScheduler是以树的方式来管理任务队列的,树中的节点类型为Schedulable,叶子节点为TaskSetManager,非叶子节点为Pool,下图是他们的继承关系:
Spark学习笔记(二)| Spark任务调度机制_第5张图片

  • FIFO:先来后到
  • FAIR: rootPool(根池)下面维持着多个子调度池,每个子调度池里面维护着一个调度队列schedulableQueue
    在FAIR模式中,需要先对子Pool进行排序,再对Pool里面的TaskSetManager进行排序,因为PoolTaskSetManager都继承自Schedulable,所以二者可以采用相同的排序算法。
    排序过程是基于Fair-share来比较的,每个要排序的对象包含三个属性,runningTasks值、minShare值、weight值。

具体的比较规则如下(遵循从1->3的顺序):

  1. runningTasksminShare小的先执行
  2. minShare使用率低的先执行(minShare使用率:runningTasks/minShare,下同)
  3. weight使用率低的先执行
  4. 以上均相等,则比较名字

3.2.2 本地化调度

本地化调度: 从调度队列中取出TaskSetManager后,遍历里面的tasks,本地化调度策略决定了取出的task给到哪个Executor去执行。
根据每个task的优先位置,确定task的Locality级别,Locality共分为五种,优先级从高到低:

名称 解析
PROCESS_LOCAL 进程本地化,task和数据在同一个Executor中,性能最好
NODE_LOCAL 节点本地化,task和数据在同一个节点中,但不在同一个Executor中,数据需要在进程间进行传输
RACK_LOCAL 机架本地化,task和数据在同一个机架的两个节点上,数据需要通过网络在节点之间进行传输
NO_PREF 对于task来说,从哪里获取都一样,没有好坏之分
ANY task和数据可以在集群的任何地方,而且不在一个机架中,性能最差

3.2.3 失败重试与黑名单机制

Task失败后的通知顺序:

  • Executor
  • SchedulerBackend
  • TaskScheduler
  • 该task对应的TaskSetManager

对于失败的Task,会记录它失败的次数,如果失败次数还没有超过最大重试次数,那么就把它放回待调度的Task池子中,否则整个Application会失败
在记录Task失败次数过程中,会记录它上一次失败所在Executor Id 和 Host,这样下次再调度该Task时,会使用黑名单机制,避免它被调度到上一次失败的节点上,起到一定的容错作用。





参考书籍: 《Spark快速大数据分析》
参考博客1
参考博客2
参考博客3
参考视频

你可能感兴趣的:(Spark)