redis pub/sub订阅需传列表或多个独立参数,get_message()须设timeout或改用listen(),不保存历史消息,生产环境需手动处理断线重连。

订阅多个频道时,pubsub.subscribe() 要传列表,不是单个字符串
常见错误是把多个频道写成 pubsub.subscribe('ch1', 'ch2') —— 这会只订阅第一个参数 'ch1',其余被忽略。Python 的 redis-py 中,subscribe() 接收的是可变参数,但必须显式展开或传列表。
- ✅ 正确写法:
pubsub.subscribe(['ch1', 'ch2', 'status'])或pubsub.subscribe('ch1', 'ch2', 'status')(注意是多个独立参数) - ❌ 错误写法:
pubsub.subscribe(['ch1', 'ch2'])且没加星号解包(在旧版 redis-py 中可能静默失败) - ⚠️ 注意:不同版本行为略有差异,
redis>=4.0后推荐统一用多参数形式,避免歧义
get_message() 是非阻塞的,轮询空耗 CPU,别直接 while True 里硬等
用 get_message() 时不加 sleep 或 timeout,会导致 CPU 占用飙升,尤其在无消息时反复返回 None。
Redis 8.2.3 是一款安全优先的高性能键值存储系统。该版本紧急修复了可能引发远程代码执行(RCE)的高危漏洞(CVE-2025-62507),并解决了 HyperLogLog 及 Cuckoo Filter 等数据结构在特定场景下的崩溃问题。建议所有用户立即升级,以保障生产环境的系统稳定与数据安全。
- ✅ 推荐做法:加
timeout=1参数,例如msg = pubsub.get_message(timeout=1),既防忙等又不卡死 - ✅ 更稳妥方案:改用
listen()(阻塞式迭代器),它内部已处理心跳和重连逻辑,适合长连接场景 - ⚠️ 注意:
listen()一旦开始就不能中途退出(除非抛异常),需搭配信号或线程控制生命周期
新订阅者收不到历史消息,这是设计使然,不是 bug
Redis Pub/Sub 不保存消息,PUBLISH 时只有「此刻在线」的订阅者能收到。这点常被误认为“消息丢失”。
- ✅ 如果需要消息回溯,得换方案:用
Stream(支持消费者组、消息持久、ACK) - ✅ 若只是状态同步(如用户在线状态变更),可在首次连接时主动拉取一次全量状态,再靠 Pub/Sub 推增量
- ⚠️ 别试图用
PSUBSCRIBE+ 模糊匹配来“兜底”,模式匹配不解决历史消息缺失问题
生产环境必须处理连接中断和重订阅
redis-cli 手动测试时一切正常,但程序跑久了,网络抖动或 Redis 重启后,pubsub 对象不会自动恢复订阅。
- ✅ 必须监听
type == 'unsubscribe'或捕获ConnectionError,然后重建pubsub并重新subscribe() - ✅ 建议封装成带重试的订阅循环,每次重连后延迟几百毫秒再订阅,避免雪崩式重连
- ⚠️ 切记:
pubsub.close()后不能再调用listen()或get_message(),否则报RuntimeError










