Spark的TaskSetManager(任务管理器)的排序算法
Spark作业执行中,有一个步骤是给任务进行资源分配,实际上这些任务由一些任务管理器TaskSetManager负责管理,资源分配过程中,会先根据某种排序算法排好序,然后根据就近原则给任务进行资源分配。那么关于TaskSetManager的排序是根据哪个算法呢?现在就来介绍。
排序算法由两种调度策略FIFOSchedulingAlorithm和FairSchedulingAlgorithm的comparator方法提供。
在FIFO调度策略中,由于根调度池rootPool直接包含了多个作业的任务管理器,在比较时,首先需要比较作业优先级(根据作业编号判断,作业编号越小,优先级越高),如果同一个作业,那就比较调度阶段(调度阶段编号越小,优先级越高)。FIFOSchedulingAlgorithm.comparator的部分源码:
override def comparator(s1:Schedulable, s2:Schedulable):Boolean = {
//获取作业编号,即作业优先级
val priority1 = s1.priority
val priority2 = s2.priority
var res = math.signum(priority1 - priority2)
//如果是同一个作业,再比较调度阶段优先级
if(res==0){
val stageId1 = s1.stageId
val stageId2 = s2.stageId
res = math.signum(stageId1 - stageId2)
}
if(res<0){
true
}else{
false
}
}
在FAIR调度策略中,包含了两层调度,第一层中,rootPool包含了调度池Pool,第二层中,Pool包含了多个TaskSetManager。其算法步骤,先获取两个调度的饥饿程度(饥饿程度:正在运行的任务是否小于最小任务,如果是,则表明该调度处于饥饿状态。其中最小任务可以通过fairscheduler.xml的minshare参数配置),有了饥饿程度,就可以比较优先级:
- 如果一个调度处于饥饿状态,另一个非饥饿状态,先满足处于饥饿状态的调度;
- 如果两个调度都处于饥饿状态,则比较资源比,先满足资源比小的调度;
- 如果两个调度都处于非饥饿状态,则比较权重比,先满足权重比小的调度;
- 如果它们的各种指标相同,则按照调度名字排序。
FairSchedulingAlgorithm.comparator的部分源码:
override def comparator(s1:Schedulable, s2:Schedulable):Boolean{
//获取配置的最小任务
val minShare1 = s1.minShare
val minShare2 = s2.minShare
//正在运行的任务
val runningTasks1 = s1.runningTasks
val runningTasks2 = s2.runningTasks
//计算饥饿状态
val s1Needy = runningTasks1<minShare1
val s2Needy = runningTasks2<minShare2
//资源比,正在运行的任务数/最小任务数
val minShareRatio1 = runningTasks1.toDouble/math.max(minShare1,1.0).toDouble
val minShareRatio2 = runningTasks2.toDouble/math.max(minShare2,1.0).toDouble
//权重比,正在运行的任务数/任务权重
val taskToWeightRatio1 = runningTasks1.toDouble/s1.weight.toDouble
val taskToWeightRatio2 = runningTasks2.toDouble/s2.weight.toDouble
if(s1Needy && !s2Needy){
//s1处于饥饿状态,s2非饥饿状态
return true
}else if(!s1Needy && s2Needy){
//s1处于非饥饿状态,s2处于饥饿状态
return false
}else if(s1Needy && s2Needy){
//s1,s2都处于饥饿状态,比较它们的资源比
compare = minShareRatio1.compareTo(minShareRatio2)
}else{
//s1,s2都处于非饥饿状态,比较它们的权重比
compare = taskToWeightRatio1.compareTo(taskToWeightRatio2)
}
if(compare < 0){
true
}else if(compare > 0){
false
}else{
//如果它们的各种指标相同,则按照调度名字排序
s1.name < s2.name
}
}