redis pub/sub不是消息队列,无法替代rabbitmq/kafka/redis streams;它无持久化、无ack、无顺序保证、不支持回溯与消费者组,仅适用于瞬时状态通知。

Redis 的发布订阅模式在分布式系统中确实容易被当作轻量级消息总线来用,但它不是 MQ,不能替代 RabbitMQ、Kafka 或 Redis Streams。直接拿来当事件总线用,大概率会在线上出问题。
订阅者离线 = 消息永久丢失
原生 PUB/SUB 不做任何消息持久化 —— PUBLISH 执行完,消息就发出去了,如果此时没有活跃的订阅者,这条消息就彻底消失。
- 哪怕只断网 2 秒,
onMessage就收不到那段时间的所有消息 -
Redis 5.0+的Streams支持消费者组和历史读取,但PUB/SUB仍不支持回溯 - Spring Data Redis 的
RedisMessageListenerContainer默认不重连,异常后监听直接终止,需手动加ConnectionFailureEventListener
慢订阅者拖垮整个 Redis 实例
旧版 Redis(6.0 之前)对输出缓冲区无硬限制,一个消费慢的 JedisPubSub 客户端可能让 Redis 内存暴涨,触发 OOM killer 杀进程。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 新版 Redis 通过
client-output-buffer-limit pubsub控制(默认32mb),超限自动断连,但业务侧看不到断连日志,表现为“突然收不到消息” - Java 中用
Redisson时,onMessage若含数据库写入或 HTTP 调用,极易阻塞 EventLoop,必须用自定义线程池包装逻辑 - Python 的
pubsub.listen()是同步阻塞迭代器,没做超时或背压控制,一旦处理卡住,整个循环挂死
频道爆炸导致内存与网络压力失控
每个订阅关系都会在 Redis server 端维护一个 client 链表,1000 个客户端各订阅 10 个频道 → server 端要维护 1 万条链表节点 + 哈希桶扩容开销。
-
pubsub numsub channel_x返回 0 不代表没人订阅 —— 可能是连接已断但 server 还没清理(尤其短连接场景) - 用通配符
psubscribe order.*时,匹配逻辑是遍历所有频道名做 glob 匹配,频道数 > 10k 时性能明显下降 - 集群模式下
PUB/SUB不跨节点 —— 订阅者必须连到同一分片,否则收不到消息;而publish命令只发给当前节点,其他节点完全不知情
无 ACK、无顺序、无分区容错
它本质是广播协议,不是消息队列:没有 delivery guarantee,不保证顺序,也不支持 consumer group 分摊负载。
- 同一个频道的多订阅者收到的消息顺序不一定一致(取决于网络延迟和 client 处理速度)
- 无法确认某条消息是否被某个特定订阅者成功处理 ——
onMessage抛异常?没人知道 - 横向扩展只能靠“多个 Redis 实例 + 应用层路由”,但
PUBLISH必须手动发到每个实例,否则消息分裂
真正需要可靠事件分发时,Redis Streams 或专业 MQ 才是正解。PUB/SUB 唯一适合的场景,是「瞬时状态通知」—— 比如服务发现心跳、配置热更新广播、开发环境调试日志推送。其余情况,别碰。










