【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实现方式,其实就是点对点的模式

(2)Pub/Sub

img

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

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

能干嘛

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

底层结构和原理说明

img

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

img

队列相关指令

img

1.XADD

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

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

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

3.XREVRANGE key end start COUNT count

根据ID降序输出

img

4.XDEL key id id ...

img

5.XLEN key

img

6.XTRIM key MAXLEN|MINID

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

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

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

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

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

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表示从头开始消费,为$表示只消费新消息

''

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

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

img

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

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

img

消费组的目的?

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

img

重点问题

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

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

img

3.XPENDING

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

img

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

img

4.XACK key group id id...

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

img

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

img

四个特殊符号

- + 最小和最大可能出现的Id
$ $表示只消费新的消息,当前流中最大的Id,可用于将要到来的信息
> 用于XREADGROUP命令,表示迄今还没有发送给组中使用者的信息,会更新消费者组的最后Id
* 用于XADD命令,让系统自动生成Id
相关推荐
Yeats_Liao2 小时前
Feed流系统设计(三):数据模型与存储设计,从表结构到Redis收件箱
java·javascript·redis
IT策士9 小时前
Redis 从入门到精通:Redis Stream —— 可靠消息队列
数据库·redis·缓存
至乐活着10 小时前
Redis缓存设计模式深度实战:击穿、穿透、雪崩及一致性终极方案
spring boot·redis·缓存穿透·缓存雪崩·缓存设计
ExC1dNtqz11 小时前
Redis 分布式锁进阶第六篇讲解
数据库·redis·分布式
小胖xiaopangss11 小时前
Redis 基础入门与实践指南
数据库·redis·缓存
kishu_iOS&AI11 小时前
Python Redis客户端 AI应用开发完整指南
人工智能·redis·ai a
我爱学习好爱好爱12 小时前
Docker Compose部署SpringBoot2+Vue3+redis项目(Rockylinux9.6):MySQL 主从复制实战
redis·mysql·docker
syt_biancheng1 天前
Redis初识
数据库·redis·缓存