概述
Redis stream 是 Redis 5 引入的一种新的数据结构,它是一个高性能、高可靠性的消息队列,主要用于异步消息处理和流式数据处理。在此之前,想要使用 Redis 实现消息队列,通常可以使用例如:列表,有序集合、发布与订阅 3 种数据结构。但是 stream 相比它们具有以下的优势:
- 支持范围查找:内置的索引功能,可以通过索引来对消息进行范围查找
- 支持阻塞操作:避免低效的反复轮询查找消息
- 支持 ACK:可以通过确认机制来告知已经成功处理了消息,保证可靠性
- 支持多个消费者:多个消费者可以同时消费同一个流,Redis 会确保每个消费者都可以独立地消费流中的消息
话不多说,接下来具体看看如何使用它。(PS:万字长文,行驶途中请系好安全带)
XADD 添加元素
XADD 命令的语法格式如下:
XADD stream-name id field value [field value]
- stream-name: 指定 redis stream 的名字
- id: 是指 stream 中的消息 ID,通常使用
*
号表示自动生成 - field value: 就是消息的内容,是 K-V 格式的键值对
关于使用 XADD 添加元素,还有以下特点:
- 自动创建流:当
my-stream
流不存在时,redis 会自动创建,然后将元素追加在流的末尾处 - 任意键值对:流中的每个元素可以包含一个或任意多个键值对
下面是一个使用 XADD 命令添加新消息的示例:
XADD my-stream * name John age 30 email john@example.com
上述命令的说明:
- 向名为
my-stream
的 Redis stream 中添加了一条新消息。 *
表示使用自动生成的消息 ID,name
、age
和email
是消息的字段名John
、30
和john@example.com
是消息的字段值。
流元素 ID
XADD 命令在成功执行后会返回元素 ID 作为结果:
"1681138020163-0"
每个元素的 ID 是一个递增的唯一标识符,由两部分组成:一个时间戳和一个序列号。
- 时间戳部分是一个 64 位的有符号整数,以毫秒为单位表示自 Unix 时间起经过的毫秒数。
- 序列号部分是一个递增的整数,从 0 开始逐步增加。
为了证明,我们可以指定消息 ID 向指定流中发送一条消息:
XADD my-stream 1681138020163-1 name Mary age 25 email mary@example.com
返回结果:
"1681138020163-1"
最后,可以提前使用 XRANGE
指令查看推入流中的数据
XRANGE my-stream - +
返回结果:
1) 1) "1681138020163-0"
2) 1) "name"
2) "John"
3) "age"
4) "30"
5) "email"
6) "john@example.com"
2) 1) "1681138020163-1"
2) 1) "name"
2) "Mary"
3) "age"
4) "25"
5) "email"
6) "mary@example.com"
流元素 ID 的限制
元素 ID 在 Redis stream 中扮演着非常重要的角色,它不仅保证了元素的唯一性和顺序性,还提供了高效的范围查询和分析功能。在使用 Redis stream 时,需要特别注意元素 ID 的限制,并保证 ID 的唯一性和递增性。
限制如下::
- ID 必须是唯一的
- 新元素的 ID 必须比流中所有已有元素的 ID 都要大
还有一些长度和特殊字符的限制等等,不符合上述限制的添加元素操作,会被 redis 拒绝,并且返回一个错误等。
最大元素 ID 是如何更新的 ?
在成功执行XADD命令之后,流的最大元素ID也会随之更新。
为什么要限制 新元素的 ID 必须比流中所有已有元素的 ID 都要大 ?
限制新元素的 ID 必须比流中所有已有元素的 ID 都要大,是为了保证 stream 中每个元素的唯一性和顺序性。这种特性对于使用流实现消息队列和事件系统的用户来说是非常重要的:用户可以确信,新的消息和事件只会出现在已有消息和事件之后,就像现实世界里新事件总是发生在已有事件之后一样,一切都是有序进行的。
自动生成 ID 的规则
示例开始就演示自动生成消息向流中推送数据,在日常使用非常方便,这里说一下它的生成规则:
- 时间戳部分是当前时间的毫秒数。表示自 Unix 时间起经过的毫秒数
- 序列号从 0 开始递增。序列号是一个 64 位的整数,从 0 开始递增
限制流长度
流的数据大多只是临时保存的,如果不对流的长度进行限制,会出现以下情况:
- 存储耗尽:随着流中消息的增加,占用的内存也会相应增加。长时间运行的应用程序可能会面临内存耗尽的风险
- 影响性能:随着数据越多,查询和操作流的速度会更慢,维护也更困难
为了避免该问题,在使用 Redis stream 时,可以使用 MAXLEN 选项指定 stream 的最大长度,命令格式如下:
XADD stream [MAXLEN len] id field value [field value ...]
示例:
XADD mini-stream MAXLEN 3 * k1 v1
XADD mini-stream MAXLEN 3 * k2 v2
XADD mini-stream MAXLEN 3 * k3 v3
XADD mini-stream MAXLEN 3 * k4 v4
# 我们向一个限制长度为 3 的 `mini-stream` 流中添加 4 条数据,然后查看流内的消息:
XRANGE mini-stream - +
1) 1) "1681140898447-0"
2) 1) "k2"
2) "v2"
2) 1) "1681140901790-0"
2) 1) "k3"
2) "v3"
3) 1) "1681140906703-0"
2) 1) "k4"
2) "v4"
最后会看到最早创建的 k1
消息已经被