设计一个分布式定时任务系统
January 27, 2022
需求和背景分析 #
一提到定时任务的使用场景,我们肯定能想到很多场景,比如:
- 每天晚上12点执行一次清理数据的任务
- 每天凌晨1点给符合条件的用户发送推广邮件
- 每个月10号结算工资
- 每隔5分钟检查一次服务器的状态
- 每天根据用户的配置,给用户发送站内消息提醒
- …
从常见的场景中,我们可以提炼出一些定时任务的特点:
序号 | 特点 | 说明 |
---|---|---|
1 | 定时 | 执行时间有规则 |
2 | 可靠 | 可以延迟执行,但不能不执行;可以不执行,但是不能多执行 |
3 | 并发(可能) | 某些场景下,可以运行多个 cron 进程来提高执行效率 |
4 | 可执行 | 这个有点废话了,但是这个关系到 cronjob 的设计,因此在这里还是提出来 |
但是作为一个系统来说,我们需要更多的功能来提升用户体验,保证平台的可靠和稳定。我们设想下以下的场景:
- 定时任务已经触发了,但是有没有执行,执行结果是什么?
- 如果一个定时任务长时间运行,那么它正常吗?
- 一个定时任务还在运行,但是下一个触发时机又到来了,该怎么办?
- 如果服务器资源已经处于高位,那么要被触发的任务还触发吗?
- …
最后,基本的访问控制,权限分配和API设计,这些都是系统功能的一部分,但不作为本文的重点考虑对象。
一些概念 #
到这里我们可以提取一些概念,来帮助我们设计一个系统:
序号 | 名词 | 解释 |
---|---|---|
1 | CronJob | 定时任务实例,描述定时任务资源的一个实体 |
2 | Job | 执行中的定时任务 |
3 | Scheduler | 调度器,负责触发 CronJob 执行和监控 Job 的执行状态;或许还会存储一些 CronJob 的状态 |
4 | JobRuntime | job 运行时,准备 Job 运行时需要的资源; 可以参考 k8s CRI |
这里 JobRuntime 是抽象化的概念,因为 Job 可以是k8s上的POD,也可以是物理机的进程,还可以是一个进程中的coroutine。
...