Redis消息队列

文章详细介绍了Redis中三种实现消息队列的方式:基于List结构的模拟队列,PubSub的点对点模型,以及Stream的完善消息队列模型。Stream支持消费者组和消息确认,能避免消息丢失,适合多消费者环境。此外,还讨论了各种模型的优缺点,如List结构的单消费者限制,PubSub的数据持久化问题,以及Stream的回溯和消息确认机制。
摘要由CSDN通过智能技术生成

消息队列

  • 存放消息的队列,最简单的消息队列模型包括三个角色:

消息队列:存储和管理消息,也称为消息代理
生产者: 发送消息到消息队列
消费者: 从消息队列获取消息并处理消息
最简单的消息队列模型

  • Redis提供了三种不同的方式来实现消息队列:

list结构:基于List结构模拟消息队列
PubSub:基本的点对点消息模型
Stream: 比较完善的消息队列模型

Redis中的消息队列

基于List结构模拟消息队列

  • 我们可以利用LPUSH结合RPOP、或者RPUSH结合LPOP来实现。
  • 但是要注意的是,当队列中没有消息时RPOP或者LPOP操作会返回null,并不像JVM的阻塞队列那样会阻塞并等待消息。
  • 因此这里应该使用BRPOP或者BLPOP来实现阻塞效果。
    List模拟消息队列
    优点:
  • 利用Redis存储,不受限于JVM内存上限
  • 基于Redis的持久化机制,数据安全性有保证
  • 可以满足消息有序性
    缺点
  • 无法避免消息丢失
  • 只支持单消费者

基于PubSub的消息队列

PubSub(发布订阅)时Redis2.0版本引入的消息传递模型。顾名思义,消费者可以订阅一个或多个channel,生产者向对应channel发送消息后,所有订阅者都能收到相关消息。

  • SUBSCRIBE channel[channel]:订阅一个或多个频道
  • PUBLISH channel msg:向一个频道发送消息
  • PSUBSCRIBE pattern[pattern]:订阅与pattern格式匹配的所有频道
    优点:

采用发布订阅模型,支持多生产、多消费
缺点:
不支持数据持久化
无法避免消息丢失。发完消息如果没人收直接丢了。
消息堆积有上限,超出时数据丢失。发布消息之后如果有消费者在监听,在消费者边会有缓存区域。在消费者没有处理完消息时,如果又来消息,这些消息都会缓存在消费者端。但是消费者端的缓存空间是有限的。

Stream

单消费者

Stream是Redis5.0引入的一种新数据类型,可以实现一个功能非常完善的消息队列。
stream发送消息命令
发送消息命令参数:

  • key 队列名称
  • [NOMKSTREAM] 如果队列不存在,是否自动创建队列,默认自动创建
  • [MAXLEN | MINID [= | ~] threshold [LIMIT count] 设置消息队列的最大消息数量,默认不设置上限
  • *|ID 消息的唯一id,*代表由Redis自动生成,格式是“时间戳-递增数字”,例如“1644804662707-0”
  • field value [field value …] 发送到队列中的消息,称为Entry,格式就是多个keu-value键值对
    例如
    创建名为users的队列,并向其中发送一个消息,内容是:{name=jack,age=21},并且使用Redis自动生成ID
XADD users * name jack age 21

读取消息:
在这里插入图片描述

  • COUNT count 每次读取消息的最大数量
  • BLOCK milliseconds 当没有消息时,是否阻塞,阻塞时长。0代表永久阻塞
  • STREAMS key [key …] 要从哪个队列读取消息,key就是队列名
  • ID [ID …] 其实id,只返回大于该ID的消息
    • 0:代表从第一个消息开始
    • $:代表从最新的消息开始
      XREAD阻塞方式,读取最新消息
XREAD COUNT 1 BLOCK 1000 STREAMS users $

在业务开发中,我们可以寻暖的调用XREAD阻塞方式来查询最新消息,从而实现持续监听队列的效果,伪代码如下

whiletrue{
	//尝试读取队列中的消息,最多阻塞2秒
	Object msg = redis.execute("XREAD COUNT 1 BLOCK 2000 STREAMS users $");
	if (msg == null) {
		continue;
	}
	//处理消息
	handleMessage(msg);
}

【注意】当我们指定其实ID为$时,代表读取最新的消息,如果我们处理一条消息的过程中,又有超过1条以上的消息到达队列,则下次获取时也只能获取到最新的一条,会出现漏读消息的问题。

STREAM类型消息队列的XREAD命令特点

  • 消息可回溯
  • 一个消息可以被多个消费者读取
  • 可以阻塞读取
  • 有消息漏读的风险

消费者组

消费者组(Consumer Group):将多个消费者划分到一个组中,监听同一个队列。具有以下特点

  • 消息分流:队列中的消息会分流给组内的不同消费者,而不是重复消费,从而加快消息处理的速度
  • 消息提示:消费者会维护一个标识,记录最后一个被处理的消息,哪怕最后消费者宕机重启,还会从标识之后读取消息,确保每一个消息都会被消费
  • 消息确认:消费者获取消息后,消息处于pending状态,并存入一个pending-list。当处理完成后,需要通过XACK来确认消息,标记消息为已处理,才会从pending-list移除。

创建消费者组:

XGROUP CREATE key groupName ID [MKSTREAM]
  • key:队列名称
  • groupName:消费者组名称
  • ID:起始ID标识,$代表队列中最后一个消息,0则代表队列中第一个消息
  • MKSTREAM:队列不存在时自动创建队列,不给补自动创建

其他常见命令

  • 删除指定的消费者组
XGROUP DESTROY key groupName 
  • 给指定的消费者组添加消费者
    一般不需要自己添加消费者,当我们从组中指定消费者并监听消息的时候,如果发现消费者不存在,会自动创建。
XGROUP CREATECONSUMER key groupName consumername
  • 删除消费者组中的指定消费者
XGROUP DELCONSUMER key groupname consumername
  • 从消费者组读消息

读消息

  • group:消费组名称
  • consumer:消费者名称,如果消费者不存在,会自动创建一个消费者
  • count:本次查询的最大数量
  • BLOCK milliseconds:当没有消息时最长等待时间
  • NOACK:无需手动ACK,获取消息后自动确认。不建议设置,有可能漏掉消息。
  • STREAMS key:指定队列名称
  • ID:获取消息的其实ID:
    • ”>“ : 从下一个未消费的消息开始
    • 其他:根据指定id从pending-list中获取已消费单未确认的消息,例如0,是从pending-list中的第一个消息开始
    • 一般情况下我们都配置”>“,当出了异常之后,再去读pending-list中 的消息。

确认消息:

XACK key group ID [ID …]
返回值为确认的消息数量

查看pending-list

XPENDING key group [ [ IDLE min-idle-time ] start end count [ consumer ] ]

  • key:队列名称
  • group:组的名称
  • IDLE min-idle-time :空闲时间,指获取消息以后,处理消息之前的时间,超过空闲时间的消息会被放进pending-list
  • start end:获取的数量。- +代表所有的。
  • consumer:获取哪个消费者的pending-list,每个消费者都有自己的pending-list
    STREAM类型消息队列的XREADGROUP命令的特点:
  • 可回溯
  • 可以多消费者争抢消息,加快消费速度
  • 可以阻塞读取
  • 没有消息漏读的风险
  • 有i消息确认机制,保证消息至少被消费一次
    独立于JVM,不会收到JVM内存限制,可以持久化,有消息确认机制,不用担心消息的漏读问题。

Redis消息队列

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值