2. Redis 作为消息队列:List、Pub/Sub、Stream 三种模式对比与选型
在异步任务与事件驱动架构中,Redis 提供了三种截然不同的消息传递模式:List、Pub/Sub 和 Stream。它们各自适用于不同的场景,选型错误会导致消息丢失、消费延迟或系统复杂度失控。本章从数据结构、消息可靠性、消费模型、适用场景四个维度进行深度对比。
2.1 三种模式核心原理
2.1.1 List 模式(阻塞队列)
基于 Redis 的 List 数据结构,通过 LPUSH 入队、BRPOP 阻塞出队实现生产者-消费者模型。消息被消费后即从队列中删除,天然支持至少一次语义。
关键命令:
# 生产者
LPUSH task_queue task_data
# 消费者(阻塞等待,超时 0 表示无限等待)
BRPOP task_queue 0
2.1.2 Pub/Sub 模式(发布/订阅)
基于频道(Channel)的广播模型。生产者向频道发布消息,所有订阅该频道的消费者实时接收。消息不持久化,消费者离线则丢失消息。
典型场景:实时通知、心跳检测、日志广播。不适合需要可靠投递的任务队列。
2.1.3 Stream 模式(消息日志)
Redis 5.0 引入的日志型数据结构。每条消息有唯一 ID,支持消费者组(Consumer Group)、消息确认(ACK)、消息回溯。兼顾了 List 的可靠性和 Pub/Sub 的广播能力。
关键命令:
# 生产者
XADD mystream * field1 value1 field2 value2
# 消费者组创建
XGROUP CREATE mystream mygroup $
# 消费者读取
XREADGROUP GROUP mygroup consumer1 COUNT 1 BLOCK 0 STREAMS mystream >
2.2 核心维度对比
| 对比维度 | List | Pub/Sub | Stream |
|---|---|---|---|
| 消息持久化 | 是(RDB/AOF) | 否 | 是(RDB/AOF) |
| 消息可靠性 | 至少一次(消费即删) | 最多一次(离线丢失) | 至少一次(ACK 确认) |
| 消费模型 | 竞争消费 | 广播消费 | 竞争 + 广播(消费者组) |
| 消息回溯 | 不支持 | 不支持 | 支持(按 ID 范围) |
| 阻塞读取 | BRPOP/BLPOP | SUBSCRIBE | XREADGROUP BLOCK |
| 消息确认 | 无(消费即确认) | 无 | XACK 显式确认 |
| 消费者组 | 无 | 无 | 有(XGROUP) |
| 消息积压处理 | 队列长度增长 | 丢弃 | 日志追加,可限流 |
| 适用版本 | 所有版本 | 所有版本 | Redis 5.0+ |
2.3 选型决策树
根据业务需求,按以下优先级进行选型:
- 是否需要消息持久化? 否 → Pub/Sub;是 → 进入下一步。
- 是否需要消息回溯/重放? 是 → Stream;否 → 进入下一步。
- 是否需要消费者组(负载均衡)? 是 → Stream;否 → 进入下一步。
- 是否需要广播消费? 是 → Stream(多消费者组);否 → List。
避坑提示:不要用 Pub/Sub 做任务队列。Pub/Sub 不持久化消息,消费者离线或网络抖动会导致消息永久丢失。如果任务队列需要“至少一次”语义,请使用 List 或 Stream。
2.4 场景推荐速查
| 业务场景 | 推荐模式 | 理由 |
|---|---|---|
| 异步任务队列(邮件、短信) | List 或 Stream | 需要持久化,至少一次语义 |
| 实时聊天/通知推送 | Pub/Sub | 低延迟广播,允许少量丢失 |
| 事件溯源/审计日志 | Stream | 需要消息回溯和持久化 |
| 多消费者负载均衡 | Stream | 原生消费者组支持 |
| 简单 FIFO 队列 | List | 实现简单,性能高 |
| 系统心跳/状态广播 | Pub/Sub | 无需持久化,实时性要求高 |
2.5 性能与可靠性权衡
- List 模式:性能最高(单线程 O(1) 操作),但缺乏消息确认机制。消费者崩溃会导致消息丢失。适合对可靠性要求不高的内部任务队列。
- Pub/Sub 模式:延迟最低(微秒级),但消息不持久化。消费者必须在线才能接收。适合实时监控、日志流等场景。
- Stream 模式:功能最全,但性能略低于 List(需要维护消息 ID 和消费者组状态)。适合需要可靠投递、消息回溯、多消费者协同的复杂场景。
性能基准参考(单节点 Redis,消息体 1KB):
List:约 100,000 ops/s(LPUSH + BRPOP)
Pub/Sub:约 80,000 ops/s(PUBLISH + SUBSCRIBE)
Stream:约 50,000 ops/s(XADD + XREADGROUP)
实际性能受网络、消息大小、消费者数量影响。
List:约 100,000 ops/s(LPUSH + BRPOP)
Pub/Sub:约 80,000 ops/s(PUBLISH + SUBSCRIBE)
Stream:约 50,000 ops/s(XADD + XREADGROUP)
实际性能受网络、消息大小、消费者数量影响。
2.6 总结
三种模式各有适用边界:
- List:简单可靠,适合轻量级任务队列。
- Pub/Sub:实时广播,适合通知类场景。
- Stream:全功能消息系统,适合企业级异步任务。
在异步任务领域,Stream 是首选,因为它同时提供了持久化、消费者组、消息确认和回溯能力。List 可作为轻量替代,Pub/Sub 仅用于非关键实时通道。