常德市网站建设_网站建设公司_腾讯云_seo优化
2026/1/12 19:43:07 网站建设 项目流程

为什么需要延时任务

我们来看一下几个非常常见的业务场景:

  1. 某电商平台,用户下单半个小时未支付的情况下需要自动取消订单。
  2. 某媒体聚合平台,每 10 分钟动态抓取某某网站的数据为自己所用。

这些场景往往都要求我们在某指定时间之后去做某个事情,也就是延时去做某个事情。

方案选择

方案类型核心优点核心缺点
定时轮询实现极简、无额外中间件、数据持久化可靠DB 压力大、实时性差、存在资源浪费
Redis ZSet低 DB 压力、支持分布式、查询效率高实时性依赖扫描间隔、需处理分布式锁
MQ 延迟队列秒级实时性、异步解耦、高并发高扩展需 MQ 插件、配置复杂、需处理消息作废
MQ 死信队列基于 MQ 原生特性、无需插件、异常消息隔离实时性略差、超时时间不灵活、消息删除复杂
时间轮算法执行效率极高(O (1))、无全量轮询、短延迟场景响应快单机版易丢任务、分布式改造需依赖 Redis + 锁、仅适配短延迟场景
1.定时轮询

基于 SpringBoot 的 Scheduled 实现,通过定时任务扫描数据库中的订单。详细实现思路:

  1. 任务配置:在 SpringBoot 项目中通过@Scheduled注解配置定时任务,可设置固定频率;(Cron 表达式:是定时任务系统定义执行时间 / 频率的核心,可设置任务按天、按月等规则执行)

  2. 扫描逻辑:任务执行时,执行 SQL 查询数据库中 "创建时间≤当前时间 - 超时阈值(如 30 分钟)且状态为待支付" 的订单;

  3. 取消处理:遍历查询结果,对每个订单先加数据库行锁(FOR UPDATE)防止并发修改,校验订单状态未变更后,执行 "更新订单状态为已取消 + 恢复商品库存" 操作

2.时间轮算法

时间轮算法是一种高效的定时任务调度算法,核心思想类似钟表的表盘:把时间分成固定的 "刻度",每个刻度对应一个待执行的任务列表;通过一个 "指针" 匀速转动,指针走到哪个刻度,就执行该刻度下的所有任务。

以 "订单 30 分钟超时取消" 为例,时间轮的实现流程可以分为 3 步:

第一步:初始化时间轮

  • 设定 1 分钟 1 个刻度、共 60 个刻度(对应 1 小时),用 Map 存 "刻度 - 订单 ID 列表";

  • 启动独立线程让指针每分钟走 1 格,超过 59 就回到 0 循环。

第二步:添加订单任务到时间轮

  • 当用户创建订单时,获取当前时间的分钟数(比如现在是 5 分)。

  • 计算订单要放入的目标刻度:当前分钟 + 超时时间(30 分钟) →5+30=35,如果超过 59 就取模(比如 50+30=80 → 80%60=20)。

  • 把订单 ID 添加到目标刻度的任务列表中,等待指针到达时处理。

第三步:指针转动,处理超时订单

  • 线程每分钟触发一次,指针向前移动 1 格,获取当前指针指向的刻度。

  • 取出该刻度下的所有订单 ID,执行取消逻辑:先加分布式锁(防止多实例重复处理)→ 校验订单状态还是 "待支付" → 更新订单状态为 "已取消" + 恢复商品库存。

  • 处理完成后,清空该刻度的任务列表,避免重复执行。

核心特点

  • 高效:无需轮询全量数据,仅处理当前刻度的到期任务,时间复杂度 O (1);

  • 适用场景:高并发、短延迟(分钟级 / 小时级)的定时任务,如订单超时、红包过期;

  • 注意:分布式场景需结合 Redis 实现时间轮集群同步,避免单机故障丢失任务。

3.Redis Zset

有序集合(Sorted Set):利用有序集合的特性,定时轮询查找已超时的任务。

  1. 数据存储:创建订单时,计算订单超时时间戳(当前时间戳 + 超时时间),将订单 ID 作为member,超时时间戳作为score,存入 Redis 有序集合;

  2. 定时扫描:通过 SpringBoot 定时任务(如每 1 分钟执行一次),执行ZRANGEBYSCORE命令筛选出score ≤ 当前时间戳的订单 ID;

  3. 分布式锁控制:扫描到超时订单 ID 后,先通过 Redis 的SETNX获取分布式锁(如SET lock:order:cancel 1 EX 30 NX),防止多实例重复处理;

  4. 取消处理:持有锁的实例遍历超时订单 ID,校验订单状态后执行取消逻辑,处理完成后通过ZREM命令将订单 ID 从有序集合中移除;

4.MQ 延迟队列
  1. 生产者发消息时,给消息设置延迟时间;

  2. 消息先发送到专门的延迟交换机(通常是x-delayed-message类型);

  3. 延迟交换机不会立即转发消息,而是暂存消息,直到延迟时间到期;

  4. 时间到后,延迟交换机将消息转发到业务队列;

  5. 消费者监听业务队列,到点接收消息并执行 "取消订单" 逻辑。

5.MQ 死信队列
  1. 消息先发送到「无消费者的普通队列」,设置队列 TTL=30 分钟,队列绑定死信交换机;

  2. 消息过期后成为死信,自动路由到死信队列,由消费端处理。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询