PSUBSCRIBE性能瓶颈源于PUBLISH时线性遍历所有pattern做glob匹配,无索引、无缓存、无短路,pattern越多越慢;大小写敏感且*不匹配空字符串,易误配;超20个pattern或100qps即引发CPU毛刺。

PSUBSCRIBE 不是“更高级的 SUBSCRIBE”,而是完全不同的订阅路径——它走的是模式匹配,不是频道直连。用错场景或写错 pattern,消息根本收不到。
pattern 写法必须严格符合 glob 规则,不是正则
Redis 的 PSUBSCRIBE 只支持 *(匹配任意长度字符)和 ?(匹配单个字符),不支持 ^、$、|、[] 等正则语法。
-
PSUBSCRIBE service.order.*✅ 匹配service.order.created、service.order.updated -
PSUBSCRIBE service.(order|payment).*❌ Redis 直接忽略该 pattern,不会报错但也不会生效 -
PSUBSCRIBE logs:202?-*✅ 匹配logs:2024-01、logs:2026-12 -
PSUBSCRIBE *.error✅ 但要注意:如果发布者发到api.error,能收到;发到db:error(含冒号)就收不到,因为:不被*跳过,只是普通字符
收到的消息格式是 pmessage,不是 message
用 PSUBSCRIBE 订阅后,收到的每条消息结构固定为 4 元素数组:"pmessage"、匹配的 pattern、实际发布的 channel、消息内容。漏解析第一个字段,容易把 pmessage 当成 message 处理出错。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 正确示例(redis-cli 输出):
1) "pmessage" 2) "service.*" 3) "service.order.created" 4) "order_id=123"
- 错误处理:直接取第 3 位当 channel、第 4 位当 payload 是对的;但如果代码里只判断
type === "message"就会跳过所有pmessage - 注意:同一个
PUBLISH service.order.created hi,若同时有SUBSCRIBE service.order.created和PSUBSCRIBE service.*,两个客户端都会收到——但前者收到的是message格式,后者是pmessage格式
pattern 数量直接影响 PUBLISH 性能
每次 PUBLISH 都要遍历所有已注册的 pattern 做 glob 匹配。100 个客户端各订阅 5 个 pattern,等于每次 publish 触发 500 次字符串匹配。
- 高频写场景(如实时风控日志)慎用
PSUBSCRIBE,优先考虑SUBSCRIBE+ 显式 channel 名 - 用
PUBSUB NUMPAT查当前总 pattern 数量,超过 1000 就该预警 - 避免重复订阅相同 pattern:一个 client 执行两次
PSUBSCRIBE logs.*,算作 2 个 pattern,不是去重的 -
PUNSUBSCRIBE logs.*只退订当前 client 的该 pattern,不影响其他 client
真正麻烦的不是怎么写 PSUBSCRIBE,而是 pattern 生效后没法动态改——改名就得客户端主动 PUNSUBSCRIBE 再 PSUBSCRIBE,且中间有窗口期收不到消息。上线前想清楚 pattern 的生命周期,比写对语法更重要。

















