-
- [方案1: 使用list做消息队列](#方案1: 使用list做消息队列)
-
-
- [问题1: 如何保证消息不丢失](#问题1: 如何保证消息不丢失)
- [问题 2: 重复消费/幂等](#问题 2: 重复消费/幂等)
-
- [方案 2: zset实现消息队列](#方案 2: zset实现消息队列)
- [方案 3: 发布/订阅(pub/sub)](#方案 3: 发布/订阅(pub/sub))
-
-
- [问题1: 如何保证消息不丢失](#问题1: 如何保证消息不丢失)
- [问题 2: 重复消费/幂等](#问题 2: 重复消费/幂等)
-
- [方案 4: Stream 实现消息队列](#方案 4: Stream 实现消息队列)
-
-
- [问题1: 如何保证消息不丢失](#问题1: 如何保证消息不丢失)
- [问题 2: 重复消费/幂等](#问题 2: 重复消费/幂等)
-
方案1: 使用list做消息队列
- 生产消息: LPUSH
- 消费消息: RPOP
问题1: 如何保证消息不丢失
- 生产者不丢失: 失败重试
- 消费者不丢失: POP同时储存到另一个(zset: score 为当前时间的时间戳)做临时备份,ACK 后删除临时备份的数据;定时将超时没有 ACK 的消息重新投入消息队列(做一个定时任务)
- redis 不丢失: 使用 kafka 类似的逻辑,集群所有从节(冗余节点)点写成功才算成功.
问题 2: 重复消费/幂等
- 唯一 Id 做去重(消费者)
方案 2: zset实现消息队列
-
zset 与 list 的核心区别
- 消费后消息不会自动在 zset 中删除,需要手动删除
- 排序方式: list 是根据加入消息的先后顺序排的;而 zset 根据 score 进行排序的
-
zset 适合做延时消息队列(比如到一段时间消费的任务)
方案 3: 发布/订阅(pub/sub)
- 生产: PUBLISH 命令
- 消费(订阅): SUBSCRIBE 命令
问题1: 如何保证消息不丢失
- 生产者不丢失: 发送失败重试
- 消费者不丢失: 消费者没有接收到消息(网络问题/之前没有消费的消息)就会丢失,无法找回!
- redis 不丢失: 使用 kafka 类似的逻辑,集群所有从节(冗余节点)点写成功才算成功.
问题 2: 重复消费/幂等
-
唯一 Id 做去重(消费者)
-
发布/订阅的方式可以有多个消费者,多次消费; 但是有消息丢失的风险
方案 4: Stream 实现消息队列
- 生产: XADD
- 普通消费: XREAD
- 消费者组消费:XREADGROUP GROUP
具体参考:https://www.runoob.com/redis/redis-stream.html
问题1: 如何保证消息不丢失
- 生产者不丢失: 失败重试
- 消费者不丢失: 有 ack 机制;在消费逻辑执行完成后再 ack,保证 "最少一次" 消费
问题 2: 重复消费/幂等
- 生产的时候使用唯一 Id 作为消息的 key
- 消费者使用唯一 Id 做去重