前言
日常开发中,我们经常会碰到有延时任务的场景,譬如30分钟后关闭订单、在指定时间上架某个活动等,如果是最简单的场景,不考虑服务水平扩容、服务宕机等因素,可能内部用github.com/robfig/cron
加MYSQL存储延时信息即可。当然,一般线上服务,不可能不考虑道这些因素的影响,所以才有很多任务调度框架,比如:Quartz、xxl-job、Temporal等。但这次这里想讨论的是中间情况,也就是,既想保证服务能水平扩容、服务宕机任务不丢失,又不想使用那些调度框架(毕竟有部署成本和学习成本)。
延时任务存储
我们知道,要想服务能够自由地水平扩缩容,服务内部不能持有数据,也就是变成无状态服务,一般我们都选择放到Redis这种缓存框架中去。那对于延时任务来说,延时时间也是一种数据,我们把它存在哪里呢?首先不管存在哪里,一定要满足以下要求:
1. 截止时间到期后,能主动通知服务
这里肯定是要用PUSH的,如果存储器没有通知能力,那么只能用轮询的方案,但一是轮询的时间间隔不好设置,二是比较吃资源,三是任务的可靠性没有保障,如果轮询服务宕机,可能任务就得不到执行。
2. 保证任务执行的唯一性
一般来说,除非特殊需要,我们只想让延时任务只执行一次,比如指定时间上架活动,假如我们水平扩展了三个节点,总不能时间到期后三个节点同时做上架活动操作,这里就需要分布式协调机制。