背景:
分布式计算模型中,如Hadoop的MR,Spark的RDD,在任务处理过程中经常会出现某个Task执行很慢,拖慢了整个批次计算。为解决此问题,Hadoop提出来了Speculative Task方案。
思路:
监控每个Task执行情况,对慢于平均进度(或者其它可以衡量进度的指标)的Task重新启动一个Task,结果集用率先完成的Task,并Kill另外没有执行完成的Task。
Spark Speculative Task实现方案
监控Slow Task:
在TaskSchedulerImpl类中启动一个独立的线程池(task-scheduler-speculation)每100ms检查一次所有Task中是否有Slow Task,
Straggler Task衡量指标:
问题描述:
在Spark计算中,每个Stage中TaskSet由N个Task组成,并由Executor端执行这些Task,在这些Task计算过程中Driver端如何评估哪些Task是Straggler Task(TaskSet中所有的Task都是并行计算,在不同的Executor中计算),这个评估过程Spark称为Speculative Task,符合Speculative Task的Task,Spark 称为Straggler Task。
首先从问题描述中抽参数,
q | 可通过spark.speculation.quantile设置,默认为0.75 |
m | 可通过spark.speculation.multiplier设置,默认为1.5 |
N | 此次TaskSet集合 |
S | 已完成的Task集合 |
R | 正在执行的Task已经花费的时间集合{r1,r2,r3...rn} |
T | 已完成的Task执行花费的时间集合{t1,t2,t3....tn} |
e | 主观认为一个Task执行时间超过e为Speculative Task,目前不可配置,默认为100ms |
1. 符合检查Speculative Task条件
|N|>1&&|S|>=(q*|N|)&&|S|>0
2. 检查哪些任务符合Straggler Task
rn>max(m*median(T),e)
从上面的两步来看,Spark的SpeculativeTask算法比较简单,此次TaskSet已经完成了75%,开始进行Speculation Task检查,当未完成的Task执行时间已经超过了max(m*median(T),e),就认为此Task为Straggler Task。
我们分析下Speculation Task实际业务场景下的作用
案例1:
从100万用户中查找出最近一个月内有订单记录的用户。假设N={n1,n2,n3},S={s1,s2},T={100,200},R={400},e=100
,假设n1有20万用户,n2有40万用户,n3 有140万用户,当|S|>=2时,会进行Speculation Task check,同时400>max(200*1.5,100),判定n3为Straggler Task,Spark会分配resource对此Task重新计算。
思考:
这个案例中发生了数据倾斜,数据都倾斜到了n3上,再重分配resource对n3进行处理,一定会快吗?答案肯定是未知的,而且从这个案例来讲,数据倾斜这么严重,肯定不会变快的,反而是浪费了计算资源,增加了整个Spark集群的压力。
我们来改进此模型,增加对Straggler Task完成率量化的变量p,
3. 检查 Straggler Task的完成率
p>=P //P为常量,如设置为0.8
当p=0.8表示Straggler Task已经完成了80%。继续上面的案例,判断n3 为Straggler Task,且p=0.8,这时可以认为没必分配一个resource对n3进行重新计算。
4. q、m的思考
下面我们继续深挖Speculative Task方案,我们先看Speculative Task方案的问题原型。例如:并行计算100个任务,出现1个任务很慢,影响了整个Job的执行时长。Spark团队提出了Speculative Task方案, 这个方案里面有两个很决策的因素。
一、执行一个任务耗时多少可以判定为Straggler Task呢?
二、计算Speculative Task最佳时间点?基于这两个问题Hadoop团队提出来了参数p、m
我们在实际
现存问题:
在分布式环境中导致某个Task执行缓慢的情况有很多,负载不均、程序bug、资源不均、数据倾斜等,而且这些情况在分布式任务计算环境中是常态。Speculative Task这种以空间换时间的思路对计算资源是种压榨,同时如果Speculative Task本身也变成了Slow Task会导致情况进一步恶化。