psubscribe 仅支持 glob 模式(*、?、[abc]),不支持正则表达式;匹配在服务端逐个进行,无索引优化,pattern 过多或过长会导致 publish 延迟上升,不适合高频业务场景。

PSUBSCRIBE 不支持正则表达式,只支持 glob 模式
Redis 的 PSUBSCRIBE 用的不是正则表达式,而是类似 shell 文件名匹配的 glob 模式(通配符),这点很多人在调试时踩坑:写了个 .*\.order\..* 发现完全不生效。它只认三种符号:*(任意字符任意长度)、?(单个任意字符)、[abc](字符类)。没有 ^、$、\d、分组或量词。
常见错误现象:PSUBSCRIBE order.*.created 能匹配 order.pay.created,但 PSUBSCRIBE order.* 无法匹配 order(末尾无点),因为 * 不会匹配空;PSUBSCRIBE order.*.? 也无效——? 必须对应一个真实字符,不能“可选”。
-
PSUBSCRIBE order.*→ 匹配order.a、order.123,不匹配order -
PSUBSCRIBE order.*.*→ 匹配order.user.created、order.pay.updated -
PSUBSCRIBE order.[0-9]*→ 匹配order.1、order.100,但不匹配order.a
Pattern 匹配发生在 Redis 服务端,但不支持动态路由或前缀树优化
每次 PUBLISH 时,Redis 会遍历所有已注册的 pattern(通过 PSUBSCRIBE 订阅的),逐个做 glob 匹配。这意味着:pattern 越多、越长,发布延迟越高;且无法利用索引加速——没有前缀共享、没有 trie 结构。线上如果挂了上百个 PSUBSCRIBE 客户端,每个监听 5–10 个 pattern,PUBLISH 延迟可能从 0.1ms 涨到 2ms+。
使用场景上,它适合低频通知(如配置变更、运维事件),不适合高频业务消息(如订单状态流、实时日志)。如果你需要按 tag、type、tenant 多维过滤,靠 PSUBSCRIBE 硬扛 pattern 组合,很快就会遇到性能瓶颈和维护混乱。
- 100 个 client × 平均 8 个 pattern = Redis 要做 800 次 glob 判断/每次 publish
- pattern 字符串越长(如
service.order.v2.us-east-1.*.failed),CPU 开销线性上升 - 不支持大小写敏感控制,glob 默认区分大小写(
Order.*≠order.*)
客户端无法得知 pattern 是否匹配成功,只能靠收不到消息反推
Redis 不提供「这个 channel 是否被任何 pattern 覆盖」的查询接口。你执行 PSUBSCRIBE user.*,再 PUBLISH user:123 login,如果没收到消息,原因可能是:user:123 不符合 user.*(冒号不是点)、pattern 拼错、client 断连、甚至 Redis 配置了 notify-keyspace-events 但没开 E 事件——你得自己逐层排除。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
调试建议:先用 redis-cli 手动复现,开启 monitor 模式看实际发了什么 channel;再确认 client 是否真的收到了 psubscribe 的确认响应(有些 SDK 会静默丢弃 subscribe 失败)。
-
redis-cli --csv PSUBSCRIBE "user.*"→ 看是否返回"psubscribe","user.*",1 -
redis-cli PUBLISH "user:123" "test"→ 注意 channel 名是user:123,不是user.123 - 检查 client 日志里有没有
Connection closed或READONLY错误干扰订阅流
真正需要模糊+灵活路由?别硬刚 PSUBSCRIBE
如果你的业务要求类似「订阅所有 us-west-2 地区、payment 相关、error 级别的消息」,或者要支持 AND/OR/NOT 组合条件,PSUBSCRIBE 的 glob 模式根本不够用。这时候更现实的做法是:用普通 SUBSCRIBE 接全量 topic(比如统一发到 events),然后在客户端做二次过滤;或者把结构化字段塞进消息体(JSON),用 consumer 自行解析 region、service、level 字段。
另一个路子是换中间件:Kafka 支持 consumer group + topic partition + key-based routing;NATS JetStream 有 subject 层级通配(foo.>)和基于 header 的 filtering;就连 Redis Streams 配合 XREADGROUP 和消息结构设计,也比硬凑 PSUBSCRIBE pattern 更可控。
glob 模式本身很简单,但一旦你开始拼接变量生成 pattern(比如 "order." + env + ".*.*"),就很容易漏转义、错层级、难审计——这些细节,在压测和灰度时才暴露出来。










