Stream队列与多线程模型
Stream队列
Redis5.0版本新出stream数据结构,是实现消息队列的功能的。
Redis Stream 的结构如上图所示,每一个Stream都有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的 ID 和对应的内容。
每个 Stream 都有唯一的名称,它就是 Redis 的 key,在我们首次使用xadd指令追加消息时创建的。
每个 Stream 都可以挂多个消费组,每个消费组会有个游标last_delivered_id在 Stream 数组之上往前移动,表示当前消费组已经消费到哪条消息了。每个消费组都有一个 Stream 内唯一的名称,消费组不会自动创建,它需要单独的指令xgroup create进行创建,需要指定从 Stream 的某个消息 ID 开始消费,这个 ID 用来初始化last_delivered_id变量。
每个消费组 (Consumer Group) 的状态都是独立的,相互不受影响。也就是说同一份 Stream 内部的消息会被每个消费组都消费到。
同一个消费组 (Consumer Group) 可以挂接多个消费者 (Consumer),这些消费者之间是竞争关系,任意一个消费者读取了消息都会使游标last_delivered_id往前移动。每个消费者有一个组内唯一名称。
消费者 (Consumer) 内部会有个状态变量pending_ids,它记录了当前已经被客户端读取,但是还没有 ack的消息。
消息 ID 的形式是timestampInMillis-sequence,时间戳-流水号。消息 ID 可以由服务器自动生成,也可以由客户端自己指定,但是形式必须是整数-整数,而且必须是后面加入的消息的 ID 要大于前面的消息 ID。建议不要自己指定
消息内容就是键值对,形如 hash 结构的键值对
生产端
生产端常用命令如下所示:
# 追加消息
# xadd stream名字 消息id key value [key value ...]
xadd streamtest * name hushang age 23
# 删除消息,这里的删除仅仅是设置了标志位,不会实际删除消息。如果不指定消息id直接执行则是删除整个stream中的消息
# xdel stream名字 消息id
xdel streamtest 165847589548-0
# 获取消息,会过滤掉删除了的消息,也可以用- + 表示获取所有消息,-表示最小值 + 表示最大值
# xrange stream名字 最小消息id 最大消息id
xrange streamtest - +
# 获取stream中消息数量
# xlen stream名字
xlen streamtest
# 删除stream
del stream名字
案例
# 首先新增三条消息
127.0.0.1:6379> xadd streamtest * name hushang age 23
"1679980604367-0"
127.0.0.1:6379> xadd streamtest * name zhangsan age 24
"1679980624235-0"
127.0.0.1:6379> xadd streamtest * name lisi age 18
"1679980635354-0"
# 查询消息
127.0.0.1:6379> xrange streamtest - +
1) 1) "1679980604367-0"
2) 1) "name"
2) "hushang"
3) "age"
4) "23"
2) 1) "1679980624235-0"
2) 1) "name"
2) "zhangsan"
3) "age"
4) "24"
3) 1) "1679980635354-0"
2) 1) "name"
2) "lisi"
3) "age"
4) "18"
127.0.0.1:6379> xrange streamtest - 1679980624235-0
1) 1) "1679980604367-0"
2) 1) "name"
2) "hushang"
3) "age"
4) "23"
2) 1) "1679980624235-0"
2) 1) "name"
2) "zhangsan"
3) "age"
4) "24"
# 获取消息数量与删除消息
127.0.0.1:6379> xlen streamtest
(integer) 3
127.0.0.1:6379