Redis Stream

417 阅读4分钟

介绍

Redis stream是redis 5.0版本新增加的数据结构。

Redis stream主要用来消息队列,Redis本身是有一个Redis(pub/sub)发布订阅来实现消息队列的,但有个缺点是消息无法持久化,如果出现网络断开,Redis宕机,消息就会被丢弃。

Stream结构是一个链表,将所有的消息都串起来,每一个消息都有一个唯一ID和对应的内容,消息是持久化的,redis重启之后,内容还在。并且能记录每一个客户端的访问位置。

image.png

每个stream都有唯一的名称,他就是Redis的key,在我们首次使用xadd指令追加消息时自动创建。

  • Consumer Group: 消费组,使用XGROUP CREATE命令创建,一个消费组可以有多个消费者
  • last_delivered_id: 游标,每个消费组都有一个游标,一个消费者组中任意一个消费组消费消息都会使这个游标移动
  • pending_ids: 维护消费者中读取到的但没有被ack掉的消息

命令

消息队列相关命令

  • XADD - 添加消息到末尾
  • XTRIM - 对流进行修剪,限制长度
  • XDEL - 删除消息
  • XLEN - 获取流包含的元素数量,即消息长度
  • XRANGE - 获取消息列表,会自动过滤已经删除的消息
  • XREVRANGE - 反向获取消息列表,ID 从大到小
  • XREAD - 以阻塞或非阻塞方式获取消息列表
1.XADD key ID field value [field value ...]
添加消息到末尾
key:队列名称,如果不存在就创建。
ID:消息 id,我们使用 * 表示由 redis 生成,可以自定义,但是要自己保证递增性
field value:消息内容


2.XTRIM key MAXLEN [~] count
对流进行修剪,限制长度
key :队列名称
MAXLEN :长度
count :数量


3.XDEL key ID [ID ...]
删除消息
key :队列名称
ID :消息ID

4.XLEN key
使用 XLEN 获取流包含的元素数量,即消息长度
key:队列名称

5.XRANGE key start end [COUNT count]
使用 XRANGE 获取消息列表,会自动过滤已经删除的消息 
key :队列名
start :开始值, - 表示最小值
end :结束值, + 表示最大值
count :数量


6.XREVRANGE key end start [COUNT count]
使用 XREVRANGE 获取消息列表,会自动过滤已经删除的消息 与上面的区别是一个从队列左边,一个是从右边。
key :队列名
end :结束值, + 表示最大值
start :开始值, - 表示最小值
count :数量

7.XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] id [id ...]
使用 XREAD 以阻塞或非阻塞方式获取消息列表,在不定义消费组的情况下,进行独立消费
count :数量
milliseconds :可选,阻塞毫秒数,没有设置就是非阻塞模式
key :队列名
id :消息 ID, 0-0表示从头开始读,$表示

消费者组相关命令

  • XGROUP CREATE - 创建消费者组
  • XREADGROUP GROUP - 读取消费者组中的消息
  • XACK - 将消息标记为"已处理"
  • XGROUP SETID - 为消费者组设置新的最后递送消息ID
  • XGROUP DELCONSUMER - 删除消费者
  • XGROUP DESTROY - 删除消费者组
  • XPENDING - 显示待处理消息的相关信息
  • XCLAIM - 转移消息的归属权
  • XINFO - 查看流和消费者组的相关信息;
  • XINFO GROUPS - 打印消费者组的信息;
  • XINFO STREAM - 打印流信息
1.XGROUP [CREATE key groupname id-or-$] [SETID key groupname id-or-$] [DESTROY key groupname] [DELCONSUMER key groupname consumername]
使用 XGROUP CREATE 创建消费者组
key :队列名称,如果不存在就创建
groupname :组名。
$ : 表示从尾部开始消费,只接受新消息,当前 Stream 消息会全部忽略。
例如:
XGROUP CREATE mystream consumer-group-name 0-0   从头开始消费
XGROUP CREATE mystream consumer-group-name $   从尾部开始消费


2.XREADGROUP GROUP group consumer [COUNT count] [BLOCK milliseconds] [NOACK] STREAMS key [key ...] ID [ID ...]
使用 XREADGROUP GROUP 读取消费组中的消息
group :消费组名
consumer :消费者名。
count : 读取数量。
milliseconds : 阻塞毫秒数。
key : 队列名。
ID : 消息 ID。为>表示接收新的消息

3.xack key group ID [ID ...]
消息标记确认

4.xgroup setid
如果你希望消费者组中的消费者重新处理流中的所有消息,可以设置下一个id为某一个消息id



GO操作Redis stream

使用第三方库: github.com/gomodule/redigo/redis

定义redis的初始化操作

image.png

封装操作redis stream的一系列方法

读取组内消息方法 image.png

单独读取消息方法,无消费组可使用这个 image.png

ack消息方法 image.png

删除消息方法 image.png

查询消费组的方法 image.png

业务处理流程大致如下

  1. 先读取消费者里 pending列表中的(表示没有被ack的消息),如果没有则读取最新消息
  2. 通过查询消费组信息,获取每个消费者最后的消息id,并让当前消息id跟其他消费者的最后id进行比较,如果其他消费者都已经读取过,则标记此消息删除(具体根据自己的业务处理)
  3. 对当前消息进行ack。
  4. 删除第二步中被标记为删除的消息。