redis pub/sub 不可替代 rabbitmq,因前者是无确认的广播机制,消息丢失是设计使然;后者提供持久化、ack、重试等完整可靠性保障,二者定位不同。

不能替代。Redis Pub/Sub 和 RabbitMQ 解决的是两类问题,混用等于把广播喇叭当电话线用——声音是传出去了,但没人确认听没听见。
Pub/Sub 的消息丢了是设计使然,不是配置没调好
Redis 的 PUBLISH 返回 OK,只代表消息写进了当前 socket 缓冲区,不表示任何订阅者收到。常见错误现象包括:
-
PSUBSCRIBE后收不到之前发布的消息——因为没连上时发的,Redis 根本不存 - 客户端网络抖动断开几秒,重连后发现漏了一整段事件——断连期间消息永久丢失
- Redis 重启后
PUBSUB CHANNELS返回空数组——不是没频道,是整个订阅状态和未投递消息全清零
它没有 unack 状态、没有 offset、没有重试队列。你没法问 Redis:“刚才那条消息谁没收到?”它只会说:“我喊了,当时在场的人听见了。”
RabbitMQ 的可靠性机制是逐层落地的
RabbitMQ 把投递责任扛在 broker 身上,不是甩给客户端。关键差异体现在:
- 消息默认进磁盘(
durable=true+delivery_mode=2),消费者宕机也不丢 -
basic.consume拉取消息后进入unack状态,崩溃或断连自动重回ready队列 - 支持 publisher confirms,生产者能明确知道消息是否已落盘
- 交换机(
Exchange)+ 队列(Queue)+ 绑定(Binding)构成可路由、可分流、可死信的完整链路
这不是“更高级”,而是角色定位不同:RabbitMQ 是消息管家,Redis Pub/Sub 是广播喇叭。
选错场景的典型线上事故
以下情况用 Pub/Sub 就是埋雷:
- 订单状态变更通知——用户支付成功后库存没扣减,因为消费端刚好 GC 暂停 2 秒断连,消息直接蒸发
- 审计日志分发——下游服务重启期间的 3 分钟操作记录全部丢失,无法补全
- 跨服务事件驱动(如用户注册后触发发邮件、发短信、更新推荐模型)——某一个下游失败,其他照常执行,但没人兜底重试
而真正适合 Pub/Sub 的场景非常窄:服务健康心跳(service:api:ping)、缓存失效通知(cache:product:1001:invalidate)、实时聊天室在线状态广播——这些都满足:允许丢失、消费者永远在线、不需要回溯、消息体极小。
别拿 Stream 或 List 去硬凑 Pub/Sub 的功能
有人试图用 LPUSH/RPOP 模拟队列,或用 XADD/XREADGROUP 强行做广播,结果语义错乱:
-
List是 FIFO 队列,但无 ACK,失败就丢;想实现“至少一次”得自己加 DB 记录 + 幂等判断 -
Stream支持消费者组和XACK,最接近 RabbitMQ,但它仍缺原生死信、TTL 延时、集群级高可用保障,运维成本不低 -
PUBSUB是纯广播,所有订阅者拿到同一份副本;Stream是多消费者组各自独立读取,语义完全不同
用错数据结构比不用还危险——它让你误以为“已经可靠了”。
真正难的不是命令怎么敲,而是判断“这条消息丢不起”还是“丢一次也无所谓”。这个判断一旦出错,后续所有代码都在为错误前提打补丁。











