【Redis】数据类型:Stream


10.redis流(Stream)

Redis Stream是Redis5.0版本新增加的数据结构。主要用于消息队列(MQ,Message Queue)。

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

而 Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端,访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。

redis常见数据类型操作命令

官网英文: https://redis.io/commands/

中文:http://www.redis.cn/commands.html

是什么

Redis5.0 之前的痛点,Redis消息队列的2种方案:

(1)List实现消息队列,List实现方式,其实就是点对点的模式img

(2)Pub/Sub

img
img

Redis5.0版本新增了一个更强大的数据结构---Stream

一句话:Stream流就是Redis版的MQ消息中间件+阻塞队列

能干嘛

实现消息队列,它支持消息的持久化、支持自动生成全局唯一ID、支持ack确认消息的模式、支持消费组模式等,让消息队列更加的稳定和可靠

底层结构和原理说明

img
img

一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的ID和对应的内容

img
img

队列相关指令

img
img

1.XADD

添加消息到队列末尾,消息ID必须要比上一个ID大,默认用星号表示自动生成ID;* 用于XADD命令中,让系统自动生成ID;

XADD用于向Stream队列中添加消息,如果指定的Stream队列不存在,则该命令执行时会新建一个Stream队列

img
img

生成的消息ID,有两部分组成,毫秒时间戳-该毫秒内产生的第一条消息

* 表示服务器自动生成MessageID(类似MySQL里面主键auto_increment),后面顺序跟着一堆业务key/value

标准语法:

# 自动生成ID(推荐)
XADD 队列名 MAXLEN ~ 最大长度 * 键1 值1 键2 值2 ...

手动指定ID(不推荐,必须严格遵守规则)

XADD 队列名 ID 键1 值1

关键参数

  • *:最常用,让 Redis 自动生成唯一消息 ID
  • MAXLEN ~ n:可选,限制队列最大长度,自动淘汰旧消息(节约内存)
  • 消息必须是 成对的 key-value,不能为空

消息 ID 规则

  1. ID 格式

固定格式:时间戳-序列号

  • 时间戳:Redis 服务器本地毫秒数
  • 序列号:同一毫秒内的自增序号,从 0 开始递增

示例:

1745000000000-0 → 第 1 条消息

1745000000000-1 → 同一毫秒的第 2 条消息

1745000000001-0 → 下一毫秒的第 1 条消息

  1. 强制约束(Redis 底层保证)
  • 全局单调递增:后一条 ID 一定 > 前一条 ID(Stream 核心特性)
  • 时钟回拨自动修复:服务器时间倒退时,Redis 不会使用更小的时间戳,沿用上一个时间戳,只递增序列号
  • 手动 ID 必须合法:格式必须是 数字-数字,且必须比上一条 ID 大

实操示例

示例 1:自动生成 ID(生产环境标准用法)

# 向 mystream 队列添加消息,自动生成ID
XADD mystream * name 张三 age 20 city 北京
# 再添加一条
XADD mystream * name 李四 age 25 city 上海

返回结果(自动生成的 ID):

1745012345678-0
1745012345679-0

示例 2:限制队列长度(防止内存爆炸)

# 队列最多保留 1000 条消息,满了自动删除旧消息
XADD mystream MAXLEN ~ 1000 * content "订单支付成功"

示例 3:手动指定 ID(仅测试用)

# 手动ID必须大于上一条
XADD mystream 1745012345680-0 content test

2.XRANGE key start end [COUNT count]

用于获取消息列表(可以指定范围),忽略删除的消息

start 表示开始值,-代表最小值

end 表示结束值,+代表最大值

count 表示最多获取多少个值

img
img

3.XREVRANGE key end start [COUNT count]

根据ID降序输出

img
img

4.XDEL key id [id ...]

img
img

5.XLEN key

img
img

6.XTRIM key MAXLEN|MINID

用于对Stream的长度进行截取,如超长会进行截取

MAXLEN 允许的最大长度,对流进行修剪限制长度

MINID 允许的最小id,从某个id值开始比该id值小的将会被抛弃

img
img

7.XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] id [id ...]

可以读取多个key

用于获取消息(阻塞/非阻塞)

​ 只会返回大于指定ID的消息,COUNT最多读取多少条消息;BLOCK是否以阻塞的方式读取消息,默认不阻塞,如果milliseconds设置为0,表示永远阻塞

非阻塞

  • $表特殊ID,表示以当前Stream已经存储的最大的ID作为最后一个ID,当前Stream中不存在大于当前最大ID的消息,因此此时返回nil
  • 0-0代表从最小的ID开始获取Stream中的消息,当不指定count,将会返回Stream中的所有消息,注意也可以使用0 (00/000也都是可以的)img

阻塞

img
img

Stream的基础方法,使用XADD存入消息,和XREAD循环阻塞读取消息的方式,可以实现简易版的消息队列

img
img

消费组相关指令

img
img

XINFO GROUPS 打印消费组的详细信息

XINFO STREAM 打印stream的详细信息

1.XGROUP CREATE key group id|$

用于创建消费组

xgroup create mystream group $

xgroup create mystream groupB 0

$表示从Stream尾部开始消费

0表示从Stream头部开始消费

创建消费组的时候必须指定ID,ID为0表示从头开始消费,为$表示只消费新消息

img''

2.XREADGROUP GROUP group [COUNT count] [BLOCK milliseconds] STREAMS key id

">",表示从第一条尚未被消费的消息开始读取

img
img

消费组groupA内的消费者consumer1从mystream消息队列中读取所有消息

但是,不同消费组的消费者可以消费同一条消息

img
img

消费组的目的?

让组内的多个消费者共同分担读取消息,所以,我们通常会让每个消费者读取部分消息,从而实现消息读取负载在多个消费者间是均衡分部的

img
img

重点问题

基于 Stream 实现的消息队列,如何保证消费者在发生故障或宕机再次重启后,仍然可以读取未处理完的消息?

Streams 会自动使用内部队列(也称为 PENDING List)留存消费组里每个消费者读取的消息保底措施,直到消费者使用 XACK命令通知 Streams"消息已经处理完成”。消费确认增加了消息的可靠性,一般在业务处理完成之后,需要执行 XACK 命令确认消息已经被消费完成

img
img

3.XPENDING

查询每个消费组内所有消费组[已读取、但尚未确认]的消息

img
img

查看某个消费组具体读取了那些数据

img
img

4.XACK key group id [id...]

向消息队列确认消息处理已完成

img
img

5.XINFO 用于打印Stream\Consumer\Group的详细信息

img
img

四个特殊符号

- + 最小和最大可能出现的Id
$ $表示只消费新的消息,当前流中最大的Id,可用于将要到来的信息
> 用于XREADGROUP命令,表示迄今还没有发送给组中使用者的信息,会更新消费者组的最后Id
* 用于XADD命令,让系统自动生成Id
posted @ 2026-06-10 17:05  青柠代码录  阅读(4)  评论(0)    收藏  举报