本文首发于个人博客,文章链接为:https://blog.d77.xyz/archives/d1007463.html
前言
最近项目中使用到了 Redis 中的 stream 数据类型作为消息队列使用,相比于其他 redis 实现的消息队列更加方便。由于是第一次使用,记录下知识点以后备用。
Stream类型
基于 redis 的消息队列有好多种实现,但是大多都有其特点和问题,本身 redis 只是个缓存啊😂,估计官方都看不下去了,这才在 redis 5.0 里加了一种数据类型专门用来实现典型的消息队列。
stream 类型几乎具备了一个消息队列所需要用到的所有功能,包括但不限于:
- 消息 ID 的序列化生成
- 消息遍历
- 处理未确认的消息
- 消息的阻塞和非阻塞读取
- 消息的分组消费
- 消息队列监控
等等…
下面介绍 stream 数据类型的使用方法。
stream类型的使用
xadd命令
语法格式为:
XADD key ID field value [field value …]
- key,用来指定 stream 的名字
- ID,用来指定 ID 值,最常用的是 *
- field value [field value …],key-value类型数据
xadd 用来在指定的 key 中添加消息,如果 key 不存在,则自动创建。添加的消息为 key-value
类型,可以一次添加多个消息。
指定 ID,最常用的是 *,表示由 redis 自动生成 ID,自动生成的 ID 为 1526919030474-55
格式,由毫秒时间戳和序列号组成,序列号用于区分同一毫秒内生成的消息,保证 ID 始终是递增的。如果由于一些其他原因系统时钟慢了,导致生成的时间戳小于了 redis 中记录的值,则会取系统中记录的最大值继续递增,保证 ID 的递增状态。
127.0.0.1:6379> xadd message 1 key1 value1 key2 value2
"1-0"
127.0.0.1:6379> xadd message 1-2 key1 value1 key2 value2
"1-2"
ID 在一般情况下是由 redis 自动指定的,但其实 ID 也是可以自定义的,为了保证 ID 的自增状态,手动指定的 ID 必须要大于系统中存在的 ID,只不过一般不这么做。
127.0.0.1:6379> xadd message * key1 value1 key2 value2
"1604475735664-0"
以上命令添加了 key1-value 和 key2-value2 两条消息到 message 这个 key 中,返回值为当前消息的 ID,由 redis 自动生成,此时消息队列中就有一条消息可以被读取了。
127.0.0.1:6379> xadd message maxlen 10 * key3 value3
"1604476672762-0"
maxlen 参数用来限制 key 中消息的最大数量,但是精确限制 key 中消息的数量是低效的,可以使用 ~
符号粗略的限制 key 中消息的数量,redis 会在可以删除整个宏结点时才去删除多余的消息,实际数量可能会比限制数量多几十个,这是正常的,但是不会少于限制的数量。
xread命令
语法格式为:
XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key …] id [id …]
- [COUNT count],用来获取消息的数量
- [BLOCK milliseconds],用来设置阻塞模式和阻塞超时时间,默认为非阻塞
- id [id …],用来设置读取的起始 ID,相当于 where id > $id,阻塞模式中可以使用 $ 来获取最新的消息 ID,非阻塞模式下无意义。
- key,指定 stream 的名字
xread 命令用于从一个或多个 key 中读取消息,仅返回 ID 值大于参数中传入的 ID 的消息。此命令有阻塞用法和非阻塞用法,如果 key 中没有消息,则返回空。
127.0.0.1:6379> xread streams message 0
1) 1) "message"
2) 1) 1) "1-0"
2) 1) "key1"
2) "value1"
3) "key2"
4) "value2"
2) 1) "1-2"
2) 1) "key1"
2) "value1"
3) "key2"
4) "value2"
3) 1) "1604476672762-0"
2) 1) "key3"
2) "value3"
以上命令在非阻塞模式输出了所有的消息,因为不存在 ID 比 0 还小的消息,所以输出了所有的消息。
阻塞模式中,可以使用 $ 符号来获取最新的消息。如果在指定超时时间内没有新的消息,则返回空。
127.0.0.1:6379> xread count 10 block 10000 streams message $
(nil)
(10.02s)
127.0.0.1:6379> xread count 10 block 10000 streams message $
1) 1) "message"
2) 1) 1) "1604478070071-0"
2) 1) "keyblock2"
2) "value"
(5.00s)
输入命令后,可以观察到命令没有任何输出,此时新开一个 redis-cli,输入 xadd message * keyblock2 value
将一条新的消息添加到 key 中,可以看到上面的命令返回了刚才添加的值和阻塞时间。
xlen命令
语法格式:
XLEN key
返回 key 中消息的数量,如果 key 不存在,则会返回 0。即使 key 中消息的数量为 0,key 也不会被自动删除,因为可能还存在和 key 关联的消费者组。
127.0.0.1:6379> xlen message
(integer) 5
返回 message 中所有消息的数量。
xrange命令
语法如下:
XRANGE key start end [COUNT count]
- key,指定 stream 的名字
- start,起始 ID
- end,终止 ID
- [COUNT count],读取的数量
该命令返回与给定的 ID 范围相匹配的消息。ID 的范围由 start 和 end 参数来指定。
127.0.0.1:6379> xrange message - +
1) 1) "1-0"
2) 1) "key1"
2) "value1"
3) "key2"
4) "value2"
2) 1) "1-2"
2) 1) "key1"
2) "value1"
3) "key2"
4) "value2"
3) 1) "1604476672762-0"
2) 1) "key3"
2) "value3"
4) 1) "1604478059261-0"
2) 1) "keyblock"
2) "value"
5) 1) "1604478070071-0"
2) 1) "keyblock2"
2) "value"
此命令由两个特殊的 ID,使用 - 表示最小的 ID 值,使用 + 表示最大的 ID 值,可以查询所有的消息。
127.0.0.1:6379> xrange message 1 1
1) 1) "1-0"
2) 1) "key1"
2) "value1"
3) "key2"
4) "value2"
2) 1)