Redis 的 List 是一个 双向链表(quicklist 实现),支持从两端高效地插入和弹出元素。
你可以把 List 当成一个先进先出的队列:
生产者使用 LPUSH
把消息推入队列(左边)
消费者使用 RPOP
弹出队列(右边)
如果用 BRPOP
,消费者会阻塞等待直到有消息可读
生产者(LPUSH) ---> [msg3, msg2, msg1] ---> 消费者(RPOP/BRPOP)
消息是一次性消费的,消费就删除
消息存储在内存中,重启会丢失(除非启用持久化 RDB/AOF)
没有“确认机制”,一旦取出就认为成功消费,失败了消息就丢了
只有一个消费者能消费某条消息(适合单消费者任务)
Redis Pub/Sub 是一种观察者模式:发布者发消息,所有订阅者都能实时收到。
订阅者用 SUBSCRIBE channel
监听频道
发布者用 PUBLISH channel message
发消息
Redis 内部维护一个“订阅表”,将消息转发给所有订阅者
---> client1 (订阅中)
/
发布者 ---> Redis ---> client2 (订阅中)
\
---> client3 (订阅中)
消息是实时广播的,一发出就推送给所有在线订阅者
订阅者必须在线,否则收不到消息(没有消息存储)
无法确认消息是否被成功处理
不适合可靠性要求高的业务(如支付、订单)
Redis Stream 是一种可持久化、可消费确认、支持多消费者组的日志结构数据类型,很像 Kafka。
每条消息都有一个唯一的 ID(时间戳+序号)
消费组(Consumer Group)可以追踪自己的消费进度
每个组有多个消费者,可以做负载均衡
可以手动 ack 确认消息
生产者(XADD)
↓
Stream(日志结构) --> 消费组A --> consumer1(读、ACK)
\--> consumer2
所有消息存储在内存+磁盘,直到被显式删除(XDEL)或设置了最大长度(MAXLEN)
自动生成或自定义,格式如:1693566729543-0
每个组有自己的消费位置指针,互不干扰
只有被消费者确认(ack)后,消息才算“处理完成”
未被 ack 的消息会留在 Pending List,可以重试(用 XPENDING 查看)
多个消费组可以重复消费同一条消息(广播型消费)
生产者发送:
XADD mystream * msg "hello"
创建消费组:
XGROUP CREATE mystream mygroup 0 MKSTREAM
消费者读取:
XREADGROUP GROUP mygroup consumer1 STREAMS mystream >
消费完成后确认:
XACK mystream mygroup 1693566729543-0
如果消费者挂掉了没 ack,另一个消费者可以用 XPENDING
查看并 XCLAIM
抢过来处理
项目 | List(列表队列) | Pub/Sub(广播) | Stream(流) |
---|---|---|---|
消息存储 | 内存(非持久) | 不存储 | 内存+磁盘持久化 |
消息可重复读 | 否 | 是(所有订阅者) | 是(消费组) |
多消费者 | ❌ | ✅ 广播 | ✅ 负载均衡+广播 |
ACK 确认机制 | ❌ | ❌ | ✅ 支持 |
离线可读 | ❌ | ❌ | ✅ 支持 |
场景推荐 | 简单任务队列 | 实时推送 | 高可用、可靠队列 |