Redis消息订阅里订单取消的那些事儿,怎么用机制保证不漏单又及时通知
- 问答
- 2026-01-18 22:07:24
- 4
在电商系统里,用户下单后可能会因为各种原因取消订单,比如改变主意了、地址填错了、或者发现别家更便宜,这个“取消订单”的动作,必须立刻、准确地通知到系统的各个相关部门,比如库存服务要赶紧把锁定的库存释放掉,优惠券服务要判断是否需要把用掉的优惠券还回去,物流系统如果已经发货了还得拦截,Redis的订阅发布功能,也就是Pub/Sub,因为它速度特别快,经常被选来做这个“喊一嗓子”的通知员,但直接用这个功能,如果不加点小心思,很容易出问题,要么是消息丢了没人听见,要么是通知晚了耽误事。
(来源:基于Redis Pub/Sub常见应用场景的描述)
直接用Redis Pub/Sub的坑:它像个大喇叭,喊完就忘
你可以把Redis的Pub/Sub想象成一个校园里的大喇叭,当订单服务要取消一个订单时,它就跑到操场中央,对着大喇叭喊:“注意啦!订单12345取消啦!”(这个过程就是发布消息),而库存服务、优惠券服务这些需要知道的部门,就像在校园各个角落竖着耳朵听广播的学生(这个过程就是订阅频道)。

这听起来很简单直接,但有几个麻烦事: 第一,消息说没就没,如果当时库存服务的同学正好去上厕所了,没听见广播,那这条“订单取消”的消息就彻底丢了,因为大喇叭(Redis)喊完这一声,它自己也不会记得喊过什么,更不会因为有人没听见就再喊一遍,这在技术上说,就是Redis的Pub/Sub模式是“非持久化”的,消息没有存在磁盘上;也是“非可靠”的,它不保证每个订阅者都能收到。 第二,来了新同学没法知道过去的事,假如优惠券服务这个同学因为机器故障重启了一下,相当于刚回到校园,他错过了故障期间的所有广播,之前取消的订单他完全不知道,也就没法处理退还优惠券了,因为大喇叭只广播此刻的消息,不会给迟到的人补课。
(来源:对Redis官方文档中关于Pub/Sub“非持久化”和“即发即忘”特性的理解)
怎么改进机制:给通知加上“双保险”

为了保证不漏单又能及时通知,我们不能只靠那个“大喇叭”,得给它配上帮手,形成一个更稳妥的机制。
第一招:先把“取消”这件事记下来,形成铁证。 订单服务在处理取消请求时,不能只去喊广播,它得先做一件更根本的事:在自己可靠的数据库里,把这个订单的状态稳稳地更新为“已取消”,这步操作必须是“原子的”,意思是要么成功,要么失败,不会出现模棱两可的状态,这笔记录就是最终的凭证,是后续所有操作的基石,就算后面通知环节出了任何问题,我们最终都可以回过头来查这张表,知道哪些订单确实被取消了,然后进行补救。
(来源:分布式系统设计中关于“状态持久化是基石”的通用原则)

第二招:用可靠的消息队列(如Redis Streams)代替大喇叭。 既然Redis自带的大喇叭(Pub/Sub)不靠谱,我们就换一个更专业的工具,Redis自己就提供了一个叫Streams的数据结构,它就像一个传送带或者排队叫号系统。 订单服务在更新完数据库后,就把“订单12345已取消”这个消息像一个包裹一样,放到这个叫Redis Streams的传送带上,库存服务、优惠券服务这些“工作人员”会一直守在传送带旁边,自己从上面拿包裹处理,每处理完一个包裹,他们就会在系统里做个标记,说“这个包裹我处理完了”。 这样做的好处太大了:
- 消息不会丢:包裹放在传送带上,会一直存在那里(可以被持久化),直到被取走,就算服务重启,回来也能接着从上次标记的地方继续取包裹,不会漏掉。
- 可以多人协作:甚至可以安排多个库存服务的工作人员一起从传送带上取不同的包裹来处理,提高效率。 这就是用更可靠的“消息队列”模式来替代“发布订阅”模式,虽然Redis Pub/Sub速度极快,适合对消息丢失不敏感的场景,但像订单取消这种关键业务,我们必须选择可靠性。
(来源:Redis官方文档中对Streams作为持久化、可回溯消息队列的介绍,以及与Pub/Sub的对比)
第三招:加上后台巡逻队——定时核对任务。 即使我们用了可靠的消息队列,理论上还是存在极小的概率出问题,比如消息队列本身可能出现故障,为了做到万无一失,我们还需要最后一道防线:一个定时任务。 这个任务就像一个后台的巡逻队,它每隔一段时间(比如每分钟)就去扫描一下订单数据库,专门查找那些状态是“已取消”、但更新时间是在几分钟之前的订单,它去核对一下库存是不是已经释放了、优惠券是不是已经返还了,如果发现有没有处理的情况,这个巡逻队就自己手动触发一下处理流程,或者至少发出一个大声的警报,让运维人员立刻介入。 这样,就算前面的通知机制在某个瞬间失效了,我们也能通过这个定期检查的“兜底”方案,最终保证数据的一致性,只不过可能会有一些延迟。
(来源:金融、电商等领域常见的“对账”或“补偿”机制思想)
总结一下 要保证订单取消不漏单又及时通知,不能单靠Redis Pub/Sub这个“大喇叭”,一个更健壮的机制是:核心靠数据库持久化状态变更,通知用可靠的消息队列(如Redis Streams)来保证必达,最后再设置一个定时核对任务作为终极保险。 这样三层下来,就能在享受Redis高速性能的同时,最大限度地避免消息丢失和延迟,确保业务能稳定运行。
本文由盘雅霜于2026-01-18发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://www.haoid.cn/wenda/83286.html
