redis 作为消息队列
消息队列的三个需求
- 消息保序
- 处理重复的消息
- 保证消息可靠性
基于List的消息队列
生产者使用LPUSH将消息写入list, 消费者使用BRPOP 取出消息。
List 本身就是按先进先出的顺序对数据进行存取的,所以可以保证消息的顺序。
对于重复消息的处理需要每个消息都有一个全局ID,消费者程序就可以对比收到的消息 ID 和记录的已处理过的消息 ID,来判断当前收到的消息有没有经过处理,从而保证幂等性。
List 本身是不会为每个消息生成 ID 号的,所以,消息的全局唯一 ID 号就需要生产者程序在发送消息前自行生成。生成之后,我们在用 LPUSH 命令把消息插入 List 时,需要在消息中包含这个全局唯一 ID,例如:
1 | LPUSH mq "101030001:stock:5" |
关于消息的可靠性可以使用 BRPOPLPUSH命令,让消费者从一个List中取出消息同时放入另一个List(备份List)中,当消费者处理完成后再从备份List中删除,如果处理中发生宕机则可以从备份List再次读取消息。
基于List的消息队列的局限
- 不支持创建多个消费组,即一个消息不能被多个不同的消费者消费。
基于 Streams 的消息队列
Redis 从 5.0 版本开始提供了 Streams 数据类型
Streams 是 Redis 专门为消息队列设计的数据类型,它提供了丰富的消息队列操作命令。
- XADD:插入消息,保证有序,可以自动生成全局唯一 ID;
- XREAD:用于读取消息,可以按 ID 读取数据;
- XREADGROUP:按消费组形式读取消息,需要被多个消费者消费则创建多个消费组;
- XPENDING 和 XACK:XPENDING 命令可以用来查询每个消费组内所有消费者已读取但尚未确认的消息,而 XACK 命令用于向消息队列确认消息处理已完成。
总结
redis 作为消息队列的优缺点
优点
- 读写性能高
- 轻量级,部署简单
缺点
- 内存有限,消息积压过多造成内存压力过大
- 可靠性不够高,可能丢失消息。比如未开启AOF同步写盘时发生宕机,或者主从切换时从库还未同步完成。