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

Redis keyspace notifications 怎样只订阅过期事件而不接收全部变更

来源:17golang原创

时间:2026-10-24 19:22:38 396浏览 收藏

如果业务只想在缓存键真正过期后做一次清理或刷新,不需要接收 Redis 的所有 SET、HSET、DEL 变更。做法是把 notify-keyspace-events 配成“通知通道 + expired 事件”的组合:需要直接拿到键名时用 Ex,需要让消息体携带事件名时用 Kx。其中 E、K 决定通道,x 才代表过期事件。

官方地址:https://redis.io/docs/latest/develop/pubsub/keyspace-notifications/

这篇只解决“只订阅过期事件”的配置选择,不把键空间通知包装成可靠消息队列。过期事件的触发时机、客户端断线和 Redis Cluster 的节点范围,都需要单独看清。

先选对通知通道:要键名还是要事件名

Redis 有两种相关频道。__keyevent@0__: 是 keyevent 通道,频道名带事件名,消息体是键名;__keyspace@0__: 是 keyspace 通道,频道名带键名,消息体是事件名。两者都能只接收 expired,只是消费端拿到的信息不同。

目标配置掩码订阅模式收到的重点
按过期键做处理Ex__keyevent@0__:expired消息体是键名
按事件类型分流Kx__keyspace@0__:消息体是 expired
notify-keyspace-events 的 E+x、K+x 与两类过期订阅通道的静态关系说明图
图1:结构说明图,比较只订阅 expired 事件时两类通道的关系;这是静态说明图,不是运行截图。

多数缓存清理场景更适合 Ex,因为订阅端直接得到键名,不需要再从频道名解析。若一个通用消费者已经按事件名分派处理,Kx 会更贴近它的消息模型。

用 Ex 或 Kx 打开最小通知范围

在 Redis 实例上临时修改配置时,可以先选择一种掩码。下面的写法只开启过期事件,不会把普通字符串、哈希或删除事件一并打开。

# E 表示 keyevent 通道,x 表示 expired 事件;两者缺一不可
redis-cli CONFIG SET notify-keyspace-events Ex

# 读取当前掩码,确认实例实际采用了哪种组合
redis-cli CONFIG GET notify-keyspace-events

# 频道中带 expired,消息体直接是发生过期的键名
redis-cli PSUBSCRIBE '__keyevent@0__:expired'

如果你需要 keyspace 形式,则把配置和订阅换成下面这一组:

# K 表示 keyspace 通道,x 表示只生成 expired 事件
redis-cli CONFIG SET notify-keyspace-events Kx

# 频道中带具体键名,消息体是 expired
redis-cli PSUBSCRIBE '__keyspace@0__:*'

CONFIG SET 只改变当前实例的运行时配置。生产环境重启后是否保留,取决于你的配置管理方式;如果 Redis 允许配置重写,可以把确认过的设置纳入持久化配置,否则应在 redis.conf 或部署模板中固定,而不是只在命令行执行一次。

三个边界:过期通知不是可靠队列

开启 Ex 或 Kx 只解决“哪些事件会被发布”,并不保证事件具备队列语义。Redis 文档明确说明,expired 事件在键被 Redis 删除时生成,不保证恰好在 TTL 降到零的瞬间生成。键被访问时发现过期,或后台过期处理清理它,都可能成为触发点。

Redis 过期事件在 TTL、惰性删除、主动过期、Pub/Sub 和集群节点之间的边界说明图
图2:边界说明图,展示 expired 通知的生成与接收条件;这是静态说明图,不是运行结果。

另外,Pub/Sub 是实时转发模型。订阅客户端断线期间,事件不会像 Stream 一样等待重放;重连后只能接收新的消息。因此它适合做缓存失效提示、临时清理触发器或低风险刷新信号,不适合承担必须不丢的账务动作、订单状态迁移或唯一一次任务。

如果使用 Redis Cluster,每个节点只发布自己负责的键空间事件,通知不会自动广播到其它节点。要覆盖全部键,需要让消费者分别订阅相关节点;这也是部署方案中必须明确的拓扑约束。

落地清单:按消费目标决定配置

  • 消费者需要键名:使用 Ex,订阅 __keyevent@0__:expired。
  • 消费者需要事件名:使用 Kx,订阅 __keyspace@0__* 或更窄的键模式。
  • 检查掩码是否包含通道字母和 x,只写 x 不能单独决定发布到哪类频道。
  • 把断线丢失、过期触发延迟和 Cluster 节点范围写进运行手册;关键任务另选可确认、可重放的队列或日志。

相关问题:

  • 为什么设置了 EXPIRE 却没收到 expired?先检查通知掩码和订阅数据库编号,再确认键是否由当前节点负责;不要把 TTL 归零时间当作事件发布时间。
  • Ex 和 Kx 能同时开启吗?可以,但会同时启用两类通道;如果消费者只需要一种消息形态,优先保持配置最小。
  • 过期通知能替代可靠队列吗?不能。Pub/Sub 断线期间不会补发,关键业务需要独立的持久化消息机制。
声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>