Skip to content
Redis 进阶数据模型与业务场景 · 第 2 篇 / 共 4 篇
领域数据与中间件
专题Redis 专题
当前序列Redis 进阶数据模型与业务场景
阅读位置第 2 篇 / 共 4 篇当前专题第 4 个序列 / 共 7 个序列

Redis Stream 和 List 队列怎么选

很多团队第一次用 Redis 做消息队列,往往是从 List + LPUSH/BRPOP 开始。
后面看到 Stream 后,又很容易觉得:

“那 List 不是可以退休了?”

其实不是。
这两个结构并不是简单的“新旧替代关系”,而是适合不同复杂度的队列需求。

先说结论

  • 只需要简单先进先出、单消费者阻塞取消息,List 通常更轻更直接
  • 需要消费组、未确认消息追踪、重试和回放能力时,优先考虑 Stream
  • 两者都不适合替代专业 MQ 去承接高可靠、跨系统、大规模异步链路
  • 选型重点不是功能多少,而是你是否真的需要“消费状态管理”

先看 List 队列在干什么

用 List 做队列,本质就是:

  • 生产者 LPUSH
  • 消费者 RPOPBRPOP

它的优势非常直接:

  • 简单
  • 命令少
  • 性能直观
  • 适合单消费链路

典型适用场景:

  • 应用内部轻量异步任务
  • 日志削峰
  • 短生命周期临时队列

List 队列的核心短板

List 最大的问题不是不能用,而是“消息被取走后,Redis 不再帮你记住它的消费状态”。

这会带来几个后果:

  • 消费者拿到消息后挂了,消息可能丢
  • 想做失败重试,要自己补处理中间状态
  • 多消费者协作时,只能靠应用层额外兜底

当然你也可以做一套 BRPOPLPUSH + processing list 之类的方案,
但这其实已经在自己手搓“半个消息中间件”了。

Stream 为什么会更像消息系统

Stream 除了保存消息本身,还引入了几个关键能力:

  • 消息 ID
  • 消费组
  • pending list
  • ack 确认

这意味着 Redis 开始帮你记录:

  • 哪条消息被谁消费了
  • 哪些消息还没确认
  • 哪些消息可能需要别人接管

这也是它比 List 更适合“需要恢复和重试”的根本原因。

一个最直观的区别

List

像把纸条从盒子里拿走。
拿走以后,盒子不知道谁拿了,也不知道纸条后来有没有处理成功。

Stream

像一本可追踪的收件登记簿。
你能看到消息是谁领走的、是否确认、哪些还没处理完。

什么时候 List 更合适

下面这些场景,List 反而比 Stream 更合适:

  • 只有一个消费逻辑
  • 丢一条消息影响不大
  • 处理失败可以容忍少量补偿
  • 你更看重实现简单

比如:

  • 站内埋点短暂削峰
  • 非核心异步通知
  • 本机任务分发

这类场景用 Stream 往往有点重。

什么时候该上 Stream

如果你开始关心下面这些问题,就应该认真考虑 Stream:

  • 消费者挂了,消息怎么办
  • 多个消费者如何协作
  • 失败消息怎么重试
  • 某条消息处理慢,能不能被别人接管
  • 能不能看到 pending 堆积

也就是说,当你开始关心“消费过程是否可见”时,Stream 的价值就出现了。

Stream 也不是白送的

很多人看到 Stream 有消费组,就误以为它可以直接替代 Kafka / RabbitMQ。
这也不准确。

你要知道它的代价:

  • 结构更复杂
  • 需要维护消费组和 ack
  • pending 长时间不清会堆积治理成本
  • 大规模消息链路和跨系统可靠投递仍不如专业 MQ 合适

Stream 更像“Redis 里最像消息队列的结构”,不是“专业 MQ 平替”。

一个实际判断模型

可以这样选:

选 List

如果你只要:

  • 简单队列
  • 单路消费
  • 逻辑轻
  • 失败影响可控

选 Stream

如果你需要:

  • 多消费者组
  • ack / pending 管理
  • 失败恢复
  • 明确的消费状态追踪

选 Kafka / RabbitMQ / RocketMQ

如果你需要:

  • 高可靠异步解耦
  • 大规模吞吐
  • 跨系统长期积压
  • 更成熟的消息治理能力

两个常见误区

1. 用 List 强行补很多消费状态

如果你已经开始自己维护:

  • 待处理队列
  • 处理中队列
  • 重试队列
  • 超时扫描

那大概率该评估 Stream 或专业 MQ 了。

2. 用 Stream 承载特别核心的大规模业务总线

Stream 能做很多事,但不是所有异步链路都应该塞进 Redis。
特别是高可靠、长堆积、跨团队消费链路,专业 MQ 会更合适。

总结

List 和 Stream 的真正区别,不在于谁更新,而在于:

  • List 更像轻量任务队列
  • Stream 更像带消费状态管理的队列

所以选型时最该问的不是“哪个功能更强”,而是“我到底需不需要让 Redis 帮我管理消费过程”。

延伸阅读相关文章优先当前专题,再补跨专题关联。
同一序列 · 顺着当前主线继续读Bitmap 和 HyperLogLog 适合什么场景适合把 Stream、Bitmap、限流和延迟队列这些进阶能力集中来看。Redis 专题 · Redis 进阶数据模型与业务场景同一序列 · 顺着当前主线继续读Redis 限流怎么设计更稳适合把 Stream、Bitmap、限流和延迟队列这些进阶能力集中来看。Redis 专题 · Redis 进阶数据模型与业务场景同专题其他序列 · 共享标签:选型对比Redis 持久化怎么选适合把持久化、内存淘汰、大 Key 和热 Key 这类稳定性问题集中来看。Redis 专题 · Redis 持久化与性能治理同专题其他序列 · 共享标签:选型对比Redis 数据结构怎么选适合把数据结构、典型场景、布隆过滤器和集群分片放在一起先打底。Redis 专题 · Redis 基础模型与高频场景跨专题关联 · 同场景:方案选型半同步复制和异步复制怎么选适合把 next-key lock、一致性读、复制延迟和分库分表边界放回同一条一致性主线上判断。MySQL 专题 · MySQL 事务、锁与高可用边界跨专题关联 · 同场景:方案选型分词器、Tokenizer 和 IK 到底怎么选适合把分词、复杂查询和深分页放到一起深入看。Elasticsearch 专题 · Elasticsearch 查询与分析细节
继续阅读Redis 进阶数据模型与业务场景当前序列第 2 篇 / 共 4 篇当前专题第 4 个序列 / 共 7 个序列
往前看
上一篇Redis String、List、Set、ZSet 怎么做业务建模回到当前序列上一章上一序列Redis 持久化与性能治理从第 1 篇开始:Redis 持久化怎么选
往后看
下一篇Bitmap 和 HyperLogLog 适合什么场景继续当前序列下一章下一序列Redis 可用性与热点治理细节从第 1 篇开始:Redis Sentinel 和主从故障切换怎么理解

把零散经验整理成可查、可复用、可持续更新的企业级知识门户