用Redis搞订单过期,省时间又简单,怎么实现的说说看
- 问答
- 2026-01-15 01:31:03
- 4
说到用Redis来处理订单过期,这确实是一个既省时间又简单的经典做法,它的核心思想就是“让专业的人干专业的事”,我们不自己写个定时任务轮询数据库去检查哪个订单超时了,而是把这个“盯梢”的活儿交给Redis这个高手来做。
为什么不用数据库轮询?
先说说为啥不直接用数据库,最直接的想法可能是:在程序里写个定时任务,比如每隔一分钟,就去数据库查一次,找出那些“待支付”状态并且创建时间超过30分钟的订单,然后把它们关掉,这个方法听起来直白,但问题很大。(来源:普遍的后端开发实践经验)
它浪费资源,哪怕一分钟只查一次,但绝大多数时候,可能根本没有订单过期,这个查询就做了无用功,白占了数据库的连接和计算资源,如果订单量非常大,这个定时任务还可能对数据库造成压力,尤其是在高峰期,这就是在给数据库“添乱”。
它不精确,定时任务是一分钟执行一次,这意味着一个订单可能刚创建完就被扫描到(因为还没超时),然后要等下一分钟才会被再次检查,这个订单的实际超时时间可能是30分钟零59秒,也可能是31分钟,存在最多一分钟的误差,对于用户体验来说,支付倒计时看着就不准了。
我们需要一个更高效、更精准的办法。
Redis怎么就成了“盯梢高手”?

Redis有一个非常好用的功能,叫做“过期键通知”或者叫“键空间通知”,你可以把它理解成Redis提供了一个“闹钟”功能。(来源:Redis官方文档关于Key-space Notifications的说明)
这个闹钟怎么用呢?简单三步走:
- 下单时设置闹钟:当用户成功创建了一个“待支付”订单,我们在Redis里存一个键值对,这个“键”可以设计成
order:expire:订单ID,对应的“值”随便设什么都可以,比如订单ID本身,这不重要,重要的是,我们在存这个键的时候,同时给它设置一个“过期时间”,比如30分钟,这就好比我们对Redis说:“喂,帮我看住这个钥匙,30分钟后它要是还在,你就把它扔掉,并且大声告诉我一声。” - Redis自动倒计时:设置好之后,你就不用管了,Redis会在内部自己进行倒计时,这个过程完全在内存里完成,速度极快,完全不会影响你的主数据库,30分钟一到,Redis就会自动删除这个键。
- 监听“闹铃响”:关键在于第三步,我们要让程序能够“听到”Redis删除这个键时发出的“闹铃声”,这个“闹铃声”就是Redis发出的一个通知,我们的应用程序可以订阅这个通知,一旦收到某个订单ID对应的键被过期的通知,我们就知道:“哦,订单XXX已经超时了!” 这时,我们的程序就可以立刻执行关单逻辑了,比如将数据库里这个订单的状态从“待支付”改为“已过期”,并释放库存。
具体怎么实现这个“监听”?
实现监听一般有两种常见方式:

一种是发布/订阅模式,让你的程序启动一个独立的线程或者服务,像收音机调频一样,订阅Redis的特定频道(就是专门广播键过期事件的频道),一旦有键过期,Redis就会往这个频道发一条消息,你的订阅服务收到消息后,就能解析出是哪个订单ID过期了,然后去处理。(来源:Redis Pub/Sub功能)
另一种更现代、更常用的方式是使用Redis的Stream数据结构,你可以把Stream想象成一个只增不减的消息队列,当键过期时,我们把过期事件当作一条消息写入这个Stream,你的应用程序可以作为一个消费者,不断地从这个Stream里拉取消息进行处理,这种方式比Pub/Sub更可靠,因为即使你的处理程序暂时挂掉了,重启后还能从上次断开的地方继续读取消息,不会丢失事件。(来源:Redis Streams介绍)
这么做的好处是啥?
对比最开始说的数据库轮询,用Redis的方案优势非常明显:
- 精准:过期时间非常精确,说是30分钟,基本就是30分钟,误差在毫秒级,用户体验好。
- 高效:所有的倒计时和检查都由Redis在内存中完成,对主数据库零压力,你的应用程序只在真正需要行动的时候(收到通知时)才去操作数据库,资源利用率极高。
- 简单:代码逻辑清晰,下单时设置一个键,然后写一个监听器处理过期事件就行了,结构非常干净。
- 解耦:订单的生成逻辑和过期处理逻辑被分开了,通过Redis这个中间件来通信,符合好的系统设计原则。
世上没有完美的方案,这个办法也有个小缺点,就是需要额外维护Redis服务,并且要确保监听过期消息的服务是高可用的,不能轻易宕机,否则还是会丢消息(不过用Stream方式可以很大程度上避免),对于绝大多数电商场景,用Redis处理订单过期都是一个非常值得推荐的、省时省力的好方法。
本文由芮以莲于2026-01-15发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://www.haoid.cn/wenda/80876.html
