news 2026/9/25 2:45:50

如何设计分布式延时消息?——以机票购买场景为例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何设计分布式延时消息?——以机票购买场景为例

前言

在真实业务中,“延时触发”是一类非常常见但又容易被低估的需求,例如:

  • 机票下单后15 分钟未支付自动取消
  • 订单创建后30 分钟关闭
  • 活动开始前定时推送通知
  • 资源锁定一段时间后自动释放

在单机系统中,这类需求实现并不复杂;
但在分布式、高并发、可扩展系统中,延时消息的设计就变得非常关键。

本文将以「购买机票超时未支付自动取消订单」为例,循序渐进讲清楚:

  • 本地延时是如何实现的
  • 本地方案的局限在哪里
  • 分布式延时消息的几种主流设计方案
  • 业界(RocketMQ)是如何解决延时消息问题的
  • 一个可落地的分布式延时消息设计思路

业务场景抽象:机票超时未支付

典型业务流程

  1. 用户下单购买机票
  2. 系统创建订单,状态为「待支付」
  3. 系统需要在15 分钟后检查订单
  • 如果已支付 → 不处理

  • 如果未支付 → 自动取消订单,释放座位

这本质上是一个:

“现在 + 延迟时间 → 执行一段逻辑”的问题

本地延时任务的实现方式(单机)

在进入分布式之前,先看最基础的实现方式。

Timer(已不推荐)

Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { cancelOrder(orderId); } }, 15 * 60 * 1000);

问题:

  • 单线程执行
  • 任务异常会影响整个 Timer
  • 无法承载高并发

ScheduledThreadPoolExecutor(推荐)

ScheduledExecutorService executor = Executors.newScheduledThreadPool(4); executor.schedule(() -> { cancelOrder(orderId); }, 15, TimeUnit.MINUTES);

优点:

  • 支持线程池
  • API 简单
  • 本地可靠性较好

本地延时方案的问题

虽然ScheduledThreadPoolExecutor很好用,但只能用于单机,在真实生产环境会遇到:

问题说明
服务重启延时任务直接丢失
集群部署多实例无法协调
扩容缩容任务归属混乱
高并发内存压力大

结论:本地延时 ≠ 分布式延时

从本地延时中抽象可复用的思想

虽然本地方案不可直接用于分布式,但它给了我们重要启发:

延时任务 = 任务 + 触发时间

换句话说,我们只要解决两个问题:

  1. 任务存在哪里

  2. 什么时候被取出来执行

分布式延时消息的核心设计思路

核心目标

  • 可靠存储:服务重启不丢任务
  • 可水平扩展
  • 时间精度可控
  • 高吞吐

分布式延时消息方案一:外部存储 + 定时扫描

设计思路

将延时消息存储在外部系统中:

(orderId, executeTime, payload, status)

然后由后台线程周期性扫描:

SELECT * FROM delay_task WHERE execute_time <= now() AND status = 'NEW' LIMIT 100;

架构示意

下单 → 写延时任务表 → 定时扫描 → 执行业务

优缺点分析

优点:

  • 实现简单
  • 可控性强
  • 易于理解

缺点:

  • 扫描数据库压力大
  • 时间精度有限(秒级)
  • 高并发下性能瓶颈明显

适合:中小规模系统

分布式延时消息方案二:Redis 实现

Redis ZSet(推荐)

利用 ZSet 的score表示时间戳:

key: delay:order score: executeTimestamp value: orderId

写入延时任务

ZADD delay:order 1700000000 order123

消费逻辑

ZRANGEBYSCORE delay:order -inf now LIMIT 0 100

取到后:

  • 执行业务
  • ZREM删除任务

优缺点

优点:

  • 性能极高
  • 实现相对简单
  • 天然支持排序

缺点:

  • Redis 内存成本
  • 数据持久性依赖 Redis 配置
  • 需要处理重复消费、幂等

业界使用非常广泛

分布式延时消息方案三:时间轮(Time Wheel)

核心思想

将时间划分为多个“槽位”:

| 0 | 1 | 2 | 3 | 4 | 5 | ... |

每个槽代表一个时间区间,任务被放入对应槽位。

特点

  • 插入和触发复杂度接近 O(1)
  • 非常适合大量延时任务

局限

  • 实现复杂
  • 精度有限
  • 通常需要多级时间轮

Netty、Kafka、RocketMQ 都采用了时间轮思想

业界成熟方案:RocketMQ 延时消息

RocketMQ 的做法

RocketMQ不支持任意时间延时,而是采用:

固定等级延时

例如:

Level延时时间
11s
25s
310s
430s
51m
......

实现原理简述

  • 延时消息写入特殊 Topic
  • 使用时间轮 + 定时调度
  • 到期后转发到真实 Topic

优缺点

优点:

  • 高性能
  • 高可靠
  • 生产级方案

缺点:

  • 延时时间不灵活
  • 强依赖 MQ

一个完整的分布式延时消息落地方案(机票)

推荐组合方案

下单 ↓ 发送延时消息(Redis ZSet / RocketMQ) ↓ 延时到期 ↓ 消费者校验订单状态 ↓ 未支付 → 取消订单

关键设计点

  • 业务幂等
  • 状态二次校验
  • 延时消息 ≠ 定时任务
  • 失败重试机制

总结

方案适用场景
本地延时单机、简单系统
DB 扫描小规模、低频
Redis ZSet高并发、灵活延时
时间轮超大规模
RocketMQ企业级

延时消息的本质不是“等多久”,而是“何时可靠地执行一次”

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 20:32:13

10个降AI率工具,本科生高效避坑指南

10个降AI率工具&#xff0c;本科生高效避坑指南 AI降重工具&#xff1a;让论文更自然&#xff0c;避免被系统“盯上” 在如今的学术环境中&#xff0c;AI生成内容&#xff08;AIGC&#xff09;已经成为许多本科生写作的一部分。然而&#xff0c;随着查重系统的不断升级&#xf…

作者头像 李华
网站建设 2026/9/25 0:12:57

9 个高效降aigc工具,继续教育学员必看!

9 个高效降aigc工具&#xff0c;继续教育学员必看&#xff01; AI降重工具&#xff1a;高效降低AIGC率&#xff0c;保持论文流畅性 在当前继续教育的学术环境中&#xff0c;越来越多的学生和教师开始关注论文的AIGC率问题。随着AI写作工具的普及&#xff0c;许多论文在内容创…

作者头像 李华
网站建设 2026/9/25 0:12:53

Python语言之“工厂函数“”与“多态方式”的异同分析探究!

Python语言之“工厂函数“”与“多态方式”的异同分析探究&#xff01; 工厂函数确实常常利用多态来创建对象&#xff0c;但它们不是同一个概念。 让我用对比的方式解释&#xff1a; 1. 相同点&#xff1a;都涉及多种类型 # 多态&#xff1a;不同类型响应相同的方法 class Anim…

作者头像 李华
网站建设 2026/9/23 15:18:04

单链表-删除中间节点的应用

思索过程&#xff1a;1.将链表从中间位置断开&#xff08;变成head->1->2->3和4->5->6两段&#xff09;2.将后半段的链表逆置&#xff08;从4->5->6变成6->5->4&#xff09;3.设置四个指针p1&#xff0c;p2&#xff0c;q1&#xff0c;q2&#xff08…

作者头像 李华
网站建设 2026/8/31 21:13:41

FreeModbus+STM32F407IGT6标准库项目代码

FreeModbus移植的文章比较多了&#xff0c;分享一个移植好可用的代码。 代码连接&#xff1a;STM32F407IGT6移植FreeModbushttps://gitee.com/zhuzheshuai/STM32F407IGT6_FreeModbus 通信使用串口和RS485两种方式&#xff0c;RS485发送/接收使能引脚用的PH9&#xff0c;可以根…

作者头像 李华
网站建设 2026/9/1 10:00:29

拥抱AI,HPE Networking以“自动驾驶的网络”引领智能网络新时代

2025年12月16日&#xff0c;HPE Networking在北京举办以“拥抱AI&#xff0c;构建自动驾驶的网络”为主题的媒体沟通会&#xff0c;首次对外分享了在完成对 Juniper Networks 收购后所推出的全新战略路线&#xff1a;以构建“安全赋能的AI原生网络”为核心举措&#xff0c;打造…

作者头像 李华