分布式任务调度系统设计

2020-10-12  本文已影响0人  LazzMan

一、思路

任务调度器、任务执行器、任务

任务调度器不关心业务逻辑,只关心任务的触发策略、失败策略、路由策略、阻塞处理策略

任务执行器只需要监听任务触发接口,按要求执行任务,成功或失败时异步通知任务调度器

任务的基本属性需要包含任务ID、触发策略、失败策略、路由策略、阻塞处理策略、创建时间、创建用户、任务参数、任务当前抢占调度器、任务状态(调度中、执行中、执行完成)

HA集群

为了避免单点故障,任务调度系统通常需要通过集群实现系统高可用,同时通过扩展提高系统的任务负载量上限。

鉴于任务调度系统的特殊性,“调度”和“执行”两个模块需要均支持集群部署,由于职责不同,因此各自集群侧重点也有有所不同。

节点故障处理

节点:
任务调度器S1、S2、S3
任务执行器E1、E2、E3
任务T1、T2、T3

情景1:

在S1上手动触发一个任务T1,T1任务信息入库(任务状态调度中),根据路由策略选择E3执行任务T1【a】(返回画面任务手动触发成功,任务状态执行中),任务T1进入E3的任务队列【b】,E3开始执行任务【c】,任务执行完成【d】,结果同步通知S2【e】(返回通知成功后才可以提交任务的事务),S2根据任务信息修改数据库T1任务信息记录【f】(任务状态执行完毕,画面定时刷新查询任务状态)

假设在【a】处时,T1发生宕机,需要保证T1的任务信息不会入库,开启DB事务,保证任务成功调度给执行器后再提交事务;画面会显示错误通知,提示调度器宕机,需要重新刷新画面,Nginx将自动选择新的S2或S3节点继续提供服务

假设在【b、c、d、e】处时,E3发生宕机,此时调度器S1、S2、S3发现E3下线(执行器下线Hook检查),在DB中查询分配给E3的任务(执行中的任务),重新抢占该任务,假设S2抢占到该任务,根据任务T1的策略调度任务,选择E1执行任务T1,T1任务执行完毕任务后异步随机通知调度器S1,S1根据任务信息修改数据库T1任务信息记录

假设在【e】处时,S2发生宕机,E3发现通知失败,将会随机重新选择可用的调度器节点再次发起通知,如果超过重试次数仍然无法通知成功(说明E3与调度器间出现了网络问题,调度器会认为E3下线),则发生异常,保证任务的事务回滚,主动通知调度器集群执行器E3故障下线,调度器集群将调度器列表中的E3排除,E3故障排除后重启E3即可重新注册到调度器中

假设在【f】处时,S2发生宕机,E3发现通知的连接异常断开,将会随机重新选择可用的调度器节点再次发起通知,如果超过重试次数仍然无法通知成功(说明E3与调度器间出现了网络问题,调度器会认为E3下线),则发生异常,保证任务的事务回滚,主动通知调度器集群执行器E3故障下线,调度器集群将调度器列表中的E3排除,E3故障排除后重启E3即可重新注册到调度器中

假设在【f】处时,E3发生宕机,S2发现响应发生异常,此时需要将事务回滚,既不能将任务状态修改为执行完毕,然后E3宕机无法向集群中心发送心跳,触发调度器的下线检查,任务将会重新被调度器抢占调度执行。

触发策略

任务的触发方式可以分为定时触发和手动触发,定时触发可以是cron表达式形式,也可以是自定义触发策略类形式。

触发策略可以是delay、FixedDelay、FixedRate、cron表达式、手动触发、以及自定义触发实现

失败策略

这里的失败策略指的是业务发生失败的处理策略,而不是因为节点故障导致任务没有执行完成导致的失败

任务失败是一种很常见的情况,当任务失败时有两点非常重要,一个是快速发现问题,另一个是及时解决问题。

任务业务逻辑千差万别,如索引同步、pv统计、订单超时处理等等。任务失败可能会导致非常严重的后果,比如索引同步任务失败可能导致搜索不匹配,pv统计失败可能导致打点报表的生成,订单超时处理任务的失败可能导致商品库存的大量无效占用等等。

针对上述情况,通常有几种处理方案:

路由策略

由于任务执行器存在多个实例,调度器如何选择任务执行器同样是个问题。

为每个任务配置不同的路由策略(为配置则使用默认路由策略)

常见的策略如下:

阻塞处理策略

任务阻塞经常发生在耗时任务场景中。举个例子,假如一个索引同步任务每10min运行一次,由于依赖的服务出现long service导致一次任务运行了15min,那么任务下次触发时将会遭遇阻塞。

在调度比较密集,而执行器来不及处理的情况下,任务阻塞策略可以指导执行器快速处理阻塞的触发请求。

常见的阻塞策略有以下几种:

上一篇下一篇

猜你喜欢

热点阅读