三种消息方案的可靠性差异
用 Redis 做消息传递有三条常见路线,可靠性差别很大。List 配合阻塞弹出实现竞争消费,简单高效但消息弹出即消失,没有确认机制;Pub/Sub 是纯广播,订阅端不在线时消息直接丢掉;Streams 提供消费者组、待处理列表与回溯读取,能实现确认与重试。选型的核心问题只有一个:这条消息能不能丢。
基本信息
| 适用平台 | List 与 Pub/Sub 为 Redis 全版本,Streams 需 5.0+ |
|---|---|
| List 关键命令 | LPUSH、BRPOP、BRPOPLPUSH、RPOPLPUSH |
| Pub/Sub 命令 | PUBLISH、SUBSCRIBE、PSUBSCRIBE |
| Streams 命令 | XADD、XREADGROUP、XACK、XAUTOCLAIM |
| 可靠性排序 | Streams 高于 List 高于 Pub/Sub |
典型使用场景
- 简单异步任务:允许偶发丢失,用 List 最省事
- 实时通知与广播:订阅端不在线即可丢弃,用 Pub/Sub
- 订单、支付类异步处理:必须确认与重试,用 Streams
- 事件总线:多个消费者组各自独立消费同一份消息流
- 延迟任务与超时重试:依赖 Streams 的待处理列表与空闲时间
三种写法对照
三种写法对照
# List:生产者推入,消费者阻塞弹出
LPUSH jobs job1
BRPOP jobs 30 # 弹出即消失,失败需自己备份
# 可靠版:弹出后放入备份队列,处理完再删除
BRPOPLPUSH jobs jobs:processing 30
# Pub/Sub:广播,订阅端不在线就丢
PUBLISH notify "deploy done"
SUBSCRIBE notify
# Streams:可确认、可重试、可回溯
XADD orders * id 1
XGROUP CREATE orders g1 0 MKSTREAM
XREADGROUP GROUP g1 c1 COUNT 10 STREAMS orders >
XACK orders g1 1737100000000-0方案对比
| 方案 | 投递模型 | ACK 与重试 | 消息是否会丢 |
|---|---|---|---|
| List | 竞争消费,一条被一个消费者取走 | 无 | 弹出后消费者失败即丢 |
| Pub/Sub | 广播,在线订阅者都收到 | 无 | 订阅端不在线期间全部丢失 |
| Streams | 消费组分片,支持回溯 | 有,PEL 与认领机制 | 可确认与重试,可控 |
| 混合用法 | Pub/Sub 通知加 Streams 兜底 | 由 Streams 保证 | 兼顾实时性与可靠性 |
List 想做到不丢,需要用弹出并放入备份队列的方式:处理成功后再从备份队列删除,处理失败可重新入队,复杂度已接近自己实现一套简化版 Streams。
把 Pub/Sub 当队列使用是常见误解:消息不做持久化,订阅端重启或断线期间的推送无人接收,业务侧表现为「通知偶尔收不到」。