消息队列
字面意思就是存放消息的队列(Message Queue 简称MQ),最简单的消息队列模型包括了三个角色:
- 消息队列:存储和管理信息,也被称为消息代理
- 生产者:发送消息到消息队列
- 消费者:从消息队列中获取消息并处理消息
Redis提供了三种不同的方式来实现消息队列:
-
list结构:基于List结构模拟消息队列(LPUSH结合BRPOP,或者RPUSH结合BLPOP来实现)
- 优点:
- 利用Redis存储,不受限于JVM内存上限
- 基于Redis的持久化机制,数据安全性有保证
- 可以满足消息有序性
- 缺点:
- 无法避免消息丢失
- 只支持单消费者
- 优点:
-
PubSub(Publish Subscribe Redis 2.0引入的消息传递模型,消费者可以订阅一个或多个channel,生产者向对应channel发送消息后,所有订阅者都能收到相关消息):基于的点对点消息模型。
- 优点:采用发布订阅模型,支持多生产、多消费
- 缺点:
- 不支持数据持久化
- 无法避免消息丢失
- 消息堆积有上限,超出时数据会丢失
-
Stream(Redis 5.0引入的一种新数据类型,可以实现一个功能非常完善的消息队列):比较完善的消息队列模型。
- 优点:
- 消息可以回溯。
- 一个消息可以被多个消费者读取。
- 可以阻塞读取(使用while(true)死循环实现)
- 缺点:有消息漏读的风险(当消费者再处理一个请求的同时队列中存入了几条新消息,根据每次获取最新消息的原则,则存入的几条新消息中除了最后一条消息会被读取,中间的消息就会被漏读)
- 优点:
综上,可以得出,使用Redis中的Stream来模拟消息队列是最合适的。但其也存在缺点,如何来规避这个漏读的风险呢?
消费者组
定义
:将多个消费者划分到一个组中,监听同一个消息队列。
消费者组具有以下特点:
- 消息对流:队列中的消息会分流给组内的不同消费者(消费者相互之间存在竞争关系),而非重复消费,从而加快消息处理的速度。
- 消息标示:消费者组会维护一个标示,记录最后一个被处理的消息(即使消费者宕机重启,也会从标示之后读取消息),可以确保每一个消息都会被消费(解决了漏读风险)。
- 消息确认:消费者获取消息后,消息会处于pending(待处理)状态,并存入一个pending-list中。当消息处理完成后需要通过XACK来确认消息,标记消息已被处理,才会从pending-list中移除。
创建消费者组
创建命令为:
XGROUP CREATE key groupName ID [MKSTREAM]
- key:队列名称
- groupName:消费者组名称
- ID:其实ID标示,$代表队列中最后一个消息,0则代表队列中第一个消息
- MKSTREAM:队列不存在时自动创建队列
其他命令:
# 删除指定的消费者组
XGROUP DESTORY key groupName
# 给指定的消费者组添加消费者
XGROUP CREATECONSUMER key groupName consumername
# 删除消费者组中的指定消费者
XGROUP DELCONSUMER key groupName consumername
从消费者中读取消息:
XREADGROUP GROUP group consumer [COUNT count] [BLOCK milliseconds] [NOACK] STREAMS key [key ...] ID [ID ...]
- group:消费者组名称
- consumer:消费者名称,如果消费者不存在,则会自动创建一个消费者
- count:本次查询的最大数量
- BLOCK milliseconds:当没有消息时最长的等待时间
- NOACK:无需手动ACK,获取到消息后自动确认
- STREAMS key:指定队列名称
- ID:获取消息的起始ID:
- “>”:从下一个消费者开始。
- “其它”:根据指定id从pending-list中获取已经消费但未确认的消息,例如0,是从pending-list中的第一个消息开始。
所以消息队列的优点有:
- 消息可回溯。
- 可以多个消费者争抢消息,加快消费速度。
- 可以阻塞读取。
- 没有消息漏读的风险。
- 有消息确认机制,保证消息至少被消费一次。
此时,可以针对Redis模拟消息队列的三种形势进行表格分析
List | PubSub | Stream | |
---|---|---|---|
消息持久化 | 支持 | 不支持 | 支持 |
阻塞读取 | 支持 | 支持 | 支持 |
消息堆积处理 | 受限于内存空间,可以利用多消费者加快处理 | 受限于消费者缓冲区 | 受限于队列长度,可以利用消费者组提高消费速度,减少堆积 |
消息确认机制 | 不支持 | 不支持 | 支持 |
消息回溯 | 不支持 | 不支持 | 支持 |