青训营笔记5 -- 分布式定时任务那些事儿(下)

169 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第5篇笔记。 今天的笔记继续整理课程“分布式定时任务那些事儿”这门课的干货内容。不得不说这一部分的内容干货好多好多啊,以至于要分两篇笔记整理完。

分布式定时任务核心架构:任务核心要解决触发、调度、执行三个关键问题 触发器Trigger 解析任务、生成出发时间 调度器Scheduler 分配任务,管理任务生命周期 执行器Executor 获取执行任务单元,执行任务逻辑

除此之外还需要提供一个控制台Admin,提供任务管理和干预的功能。

控制台: 任务:Job 任务元数据 任务实例:JobInstance 任务运行的实例。 任务结果:JobResult 任务实例运行的结果。 任务历史:JobHistory 用户可以修改任务信息,任务实例对应的任务元数据可以不同,因而使用任务历史存储。

任务元数据:Job 是用户对任务属性定义,包括任务类型调度时机、执行行为等。 基础信息 who 调度时机 when 执行行为 what 执行方式 how

任务实例:是一个确定的Job的一次运行实例 Job_id 触发时间 状态&结果 过程信息

触发器:核心职责:给定一系列任务,解析它们的触发规则,在规定的时间点触发任务的调度。

设计约束:需支持大量任务,需支持秒级的调度,周期任务需要多次执行,需要保证秒级扫描的高性能,避免资源浪费。

方案1 定期扫描+延时消息 方案2 时间轮Quartz 所用方案 时间轮是一种高效利用现成资源进行批量化调度的一种调度模型,时间轮是一个存储环形队列,底层采用数组实现,数组中的每个元素可以存放一个定时任务列表。

目标:遍历任务列表,从中找出当前时间点徐出发的任务列表。 使用链表存储任务 使用最小堆存储任务,按执行时间排序,每个节点存储同执行时间任务列表。 查询复杂度O(1) 修改复杂度O(log n) 使用时间轮存储任务,每个节点存储同执行时间任务列表 使用多级时间轮存储任务,上一级时间轮转过对应刻度后把任务塞入下级时间轮中

触发器--高可用 核心问题:不同业务之间任务调度互相影响怎么办? 负责扫描和触发的机器挂了怎么办? 解法思路:存储上不同国别、业务做资源隔离;运行时不同国别、业务分开执行;部署时采用多机房集群化部署,避免单点故障,通过数据库锁或分布式锁保证任务只被触发一次。

接下来讲师举了几个实际的例子,例如多个Trigger,避免任务被同时触发。 数据库行锁模式:触发调度之前更新数据库中JobInstance状态,成功抢锁的才会触发调度 分布式锁模式:在触发调度之前尝试抢占分布式锁,可使用Redis锁或Zookeeper锁。

调度器 资源来源:业务系统提供机器资源、定时任务平台提供机器资源。

节点选择:随机节点执行:选择集群中一个可用的执行节点执行调度任务。 广播执行:在集群中所有的执行节点分发调度任务并执行。 分片执行:按照用户自定义分片逻辑进行拆分,分发到集群中不同节点并行执行。 任务分片:提高任务执行效率和资源利用率。

N个执行器Executor,M个业务数据区段,最好M>=N 且M是N的整数倍。

任务编排: 使用有向无环图DAG(Directed Acyclic Graph)进行可视化任务编排

故障转移:确保部分执行单元任务失败时,任务最终成功。 分片任务基于一致性hash策略分发任务,当某Executor异常时,调度器会将任务分发到其他Executor。

调度器可以集群部署,做到完全的无状态,靠消息队列的重试机制保障任务一定会被调度。

执行器:基于注册中心,可以做到执行器的弹性扩容与缩容。

业务应用:所有需要定时、延时、周期性执行任务的业务场景都可以考虑使用分布式定时任务。 电商:30分钟未付款自动关闭订单,定时给用户发放优惠券等。 互动:支付宝集五福,春节集卡瓜分红包。 游戏:活动结束后批量补发用户未领取的奖励。