Redis Pub/Sub 是无存储的实时广播机制,消息断连即丢;Stream 是带 ACK 的持久化消息队列,支持回溯、消费者组和精确控制。若业务允许消息丢失且追求极低延迟,选 Pub/Sub;若需确保消息必达且可重试,选 Stream。
先说结论:Pub/Sub 适合实时通知,Stream 适合可靠任务队列,两者不是替代关系而是场景互补。
- 适合:实时性压倒一切且允许丢失选 Pub/Sub,要求消息不丢且可回溯选 Stream。
- 重点看:Stream 必须显式管理消费者组(XGROUP)和消息确认(XACK)。
- 别忽略:Pub/Sub 订阅者离线期间消息彻底消失,无法通过重启恢复。
命令速用版
Pub/Sub 模式仅需发布和订阅命令,Stream 模式需管理消息 ID 和确认状态。
# Pub/Sub 发布与订阅
PUBLISH channel_name "message"
SUBSCRIBE channel_name
# Stream 生产与消费
XADD mystream * field1 value1
XGROUP CREATE mystream mygroup 0
XREADGROUP GROUP mygroup consumer1 COUNT 1 BLOCK 5000 STREAMS mystream >
XACK mystream mygroup 1743405096987-0为什么会这样
Pub/Sub 是无状态代理,Stream 是独立数据结构。Pub/Sub 消息仅在发布瞬间存在于内存通道,无订阅者则直接丢弃,不写 AOF 也不进 RDB。Stream 消息持久化在内存链表中,每个消息有唯一 ID(时间戳 + 序列),支持按范围查询和重复读取。
Stream 的可靠性依赖消费者组机制,消息读取后进入 Pending Entries List(PEL),只有显式发送 XACK 才会移除。若消费者宕机未确认,消息会保留在 PEL 中,其他消费者可通过 XPCLAIM 接管,实现故障转移。
分步处理
根据可靠性需求选择模式,并配置相应的持久化与确认策略。
1. 评估丢失容忍度
若消息丢失不影响业务(如在线人数广播、开发环境日志),使用 Pub/Sub。若消息丢失会导致数据不一致(如订单处理、支付通知),必须使用 Stream。
2. 配置 Stream 消费者组
创建消费者组时指定起始 ID,0 表示从头开始,$ 表示从新消息开始。生产环境建议使用 0 确保历史消息不丢失,配合 XACK 确保至少一次消费。
3. 管理内存占用
Stream 消息默认不自动删除,需在 XADD 时使用 MAXLEN 参数限制最大长度,或定期调用 XTRIM 清理旧消息,防止内存溢出。
怎么验证是否生效
通过模拟断连和检查 pending 列表来验证可靠性机制。
1. 验证 Pub/Sub 丢失
启动订阅者后断开网络,期间发布者发送消息,重连后订阅者无法收到断连期间的消息,证明无持久化。
2. 验证 Stream 重投
消费者读取消息后不发送 XACK 直接宕机,重启新消费者读取同一组,消息会再次出现,证明 PEL 机制生效。
3. 检查 Pending 列表
使用 XPENDING mystream mygroup 查看未确认消息数量,若数量持续增长说明消费逻辑未正确调用 XACK。
常见坑
忽略 Stream 的确认机制会导致内存泄漏,误用 Pub/Sub 做关键业务会导致数据丢失。
1. 忘记 XACK
不调 XACK 的后果不是消息重复,而是 PEL 不断膨胀,最终拖慢整个 Stream 的读取性能并占用大量内存。
2. 误用 Pub/Sub 做队列
Pub/Sub 所有订阅者都会收到相同消息,无法实现负载均衡,且消费者重启后无法补发离线消息。
3. Stream ID 误解
Stream 消息 ID 是 millisecondsTime-sequence 格式,不能自定义业务主键,填错会直接报错 ERR Invalid stream ID。
常见问题
Pub/Sub 消息能持久化吗?
不能。Pub/Sub 消息不写 AOF 不进 RDB,纯内存一闪而过,订阅者离线即丢失。
Stream 消费者宕机怎么办?
消息会留在 Pending 列表中,其他消费者可通过 XPCLAIM 接管超时消息,实现故障转移。
哪个性能更高?
Pub/Sub 更轻量,吞吐量更高;Stream 因持久化和 ACK 机制,CPU 和内存占用更高,延迟略高但仍为毫秒级。
参考来源
- Redis 5.0 中 Stream 与 Pub/Sub 有什么核心区别_深度剖析消息传递架构差异
- 硬核| Redis 消息队列深度实战:从 Pub/Sub 到 Stream,一文打尽所有通信
- Redis 消息队列:Pub/Sub 与 Stream 对比
- 性能比拼:Redis Streams vs Pub/Sub
- 深入解析 Redis 消息队列:三种实现方式的优劣与实践