登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  Redis

Redis 过期事件监听实践:用 Keyspace Notifications 做轻量补偿

来源:17golang原创

时间:2026-06-29 12:07:25 181浏览 收藏

Redis 的过期 Key 常被当作“自然清理”机制使用:会话 30 分钟失效、验证码 5 分钟失效、临时任务状态 10 分钟失效。问题是,很多业务不只想让 Key 消失,还希望 Key 过期时顺手做一点补偿动作,比如标记会话超时、写一条业务日志、触发轻量清理。

Redis Keyspace Notifications 可以把 Key 变化通过 Pub/Sub 发出来。本文用“监听过期 Key 做轻量补偿”这个场景,讲清楚它能做什么、怎么快速试用、和定时扫描有什么区别,以及为什么不能把它当成可靠任务队列。

目录

  • 消息是什么:过期事件进入 Pub/Sub
  • 适用场景:只适合轻量提醒和辅助补偿
  • 快速试用:开启过期事件并订阅频道
  • 和旧方案对比:事件通知与定时扫描怎么配合
  • 采用风险:事件通知不能当可靠队列
  • 落地检查:上线前确认配置、兜底和指标

消息是什么:过期事件进入 Pub/Sub

Keyspace Notifications 的工作方式可以理解为:Redis 内部发生某类 Key 事件后,把事件发布到特定 Pub/Sub 频道。对过期事件来说,常见频道是 __keyevent@0__:expired,其中 0 表示数据库编号。

默认情况下,这类通知是关闭的。要监听过期事件,需要配置 notify-keyspace-events,例如只关注 keyevent 的 expired 事件,可以使用 Ex

Redis 过期事件从写入 TTL、过期事件、事件通道、监听服务到补偿动作的分层链路
过期事件监听的核心链路是:写入带 TTL 的 Key,Redis 发布过期事件,监听服务消费事件后做轻量补偿。
redis-cli CONFIG SET notify-keyspace-events Ex
redis-cli --csv PSUBSCRIBE '__keyevent@0__:expired'

另开一个终端写入带过期时间的 Key:

redis-cli SET session:1001 ok EX 30

等待 Key 过期后,订阅端会收到类似 session:1001 的消息。注意,消息体通常是 Key 名,不包含完整 value;如果补偿动作需要业务详情,应该提前把必要信息写到数据库或另一份可查询记录中。

适用场景:只适合轻量提醒和辅助补偿

这个能力适合“收到提醒后做一点补充动作”的场景,不适合承载必须成功的核心流程。

场景 适合程度 建议做法
临时会话过期后写审计日志 适合 监听过期事件,异步标记超时
验证码过期后清理辅助状态 适合 事件提醒加低频补扫
订单超时自动取消 谨慎 应以数据库状态和定时补偿为准
支付、库存扣减等强一致动作 不建议 使用可靠队列、数据库事务或专门调度系统

判断标准很简单:如果漏掉一个事件只会让补偿稍晚发生,可以考虑;如果漏掉一个事件会导致资金、库存、订单状态错误,就不要只依赖它。

快速试用:开启过期事件并订阅频道

先在测试环境确认配置和订阅链路。生产环境启用前,要评估事件量和监听服务稳定性。

1. 查看当前配置

redis-cli CONFIG GET notify-keyspace-events

如果返回空字符串,说明通知没有开启。

2. 开启过期事件

redis-cli CONFIG SET notify-keyspace-events Ex

E 表示 keyevent 类型通知,x 表示 expired 事件。这里只开启最小范围,避免把无关写入、删除、修改事件全部发布出来。

3. 订阅过期事件频道

redis-cli PSUBSCRIBE '__keyevent@0__:expired'

4. 写入测试 Key

redis-cli SET timeout:order:1001 pending EX 5

订阅端收到 timeout:order:1001 后,就可以由监听服务解析业务类型和编号,做轻量补偿,例如写日志、更新一条状态记录或打指标。

和旧方案对比:事件通知与定时扫描怎么配合

很多团队原来会用定时任务扫描超时数据。扫描的优点是可重复、可兜底;缺点是延迟取决于周期,且扫描范围大时会增加系统压力。Keyspace Notifications 的优点是接近实时;缺点是 Pub/Sub 通知不保存离线消息。

方案 优点 风险 推荐位置
只用事件通知 响应快,代码链路短 监听端离线时可能漏消息 轻量提醒
只用定时扫描 可重复检查 有周期延迟,扫描成本较高 状态最终修正
事件通知 + 低频补扫 实时性和可靠性更均衡 实现略复杂 推荐组合

更稳的组合是:事件通知负责快速触发,低频扫描负责补漏,指标负责确认。例如监听服务收到 timeout:order:1001 后立即处理;每 5 分钟再扫描数据库里仍处于 pending 且已经超时的订单,补齐漏掉的动作。

采用风险:事件通知不能当可靠队列

Redis 官方文档明确说明,这类通知基于 Pub/Sub。Pub/Sub 的特点是实时发布,但不会为离线订阅者保留消息。也就是说,监听服务重启或网络短暂断开时,这段时间发布的事件可能收不到。

Redis 事件通知的采用风险:默认关闭、可能丢失、不精确,需要补扫兜底和指标确认
把事件通知当提醒,把补扫和指标当兜底,才是更可靠的过期事件处理闭环。

还有一个容易误解的点:过期事件不等于“TTL 到 0 的那一毫秒立刻通知”。Redis 过期删除既有访问时惰性删除,也有后台周期清理,因此事件到达时间可能有轻微延迟。对秒级精度要求很高的任务,应使用专门的延迟队列或调度系统。

落地检查:上线前确认配置、兜底和指标

上线前建议按这份清单检查:

  • 只开启需要的事件类型,例如过期事件使用 Ex,不要一口气打开全部通知。
  • 监听服务能自动重连,并在重连后继续订阅目标频道。
  • 事件处理逻辑是幂等的,同一个 Key 被重复处理也不会产生脏数据。
  • 核心业务状态以数据库或可靠存储为准,事件通知只做提醒和辅助补偿。
  • 有低频补扫任务,能发现监听服务离线期间漏掉的超时数据。
  • 记录 expired_events_total、处理成功数、处理失败数和补扫命中数。

总结一下,Redis Keyspace Notifications 很适合做“轻量、接近实时、可补偿”的过期事件提醒。它的正确位置不是替代任务队列,而是和定时补扫、数据库状态、指标告警一起组成处理闭环。只要边界定清楚,就能在不引入复杂调度系统的情况下,解决一批临时状态过期后的辅助处理问题。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>