本文已收录于专栏
上千人点赞收藏,全套Redis学习资料,大厂必备技能!
目录
1、简介
Stream弥补了Redis作为MQ(message queue)技术选型上的不足之处;Redis 5.0发布的Stream相比Pub/Sub模块,Stream支持消息持久化,结合sentinel或cluster使其成为了一个比较可靠的消息队列。尽管我认为它很难成为公司MQ的技术选型产品,但是关于Stream的使用和特性(消费组),仍值得一探究竟。
Stream对标消息队列,因此几乎具备了MQ所有的特性,以下列出Stream所具有的部分特性:
- 消息顺序存储
- 消息ID序列化规则生成
- 消息的遍历
- 消息阻塞/非阻塞式获取
- 客户端分组消费消息
- 消息确认机制
- 消息异常机制
- 消息队列监控
在文中也会说到Stream的这些特性。
2、Stream内部探索
2.1 Stream 结构
在探索Stream的内部结构之前,先看一张清晰的Stream结构图:
如下是关于上图的名词解析:
- Message Content:消息内容
- Consumer group:消费组,通过XGROUP CREATE 命令创建,一个消费组可以有多个消费者
- Last_delivered_id:游标,每个消费组有一个游标,任意消费者读取消息后,游标都会向前移动
- Consumer:消费者,消费组中的消费者
- Pending_ids:状态变量,每个消费者会有一个状态变量,用于记录被当前消费者读取,但是并未ack的消息id
2.2 四个唯一
Stream内部维护了一个消息链表,以此使得消息能够具有队列的特性。在Stream中有四个唯一需要了解:
- 每个Stream都具有唯一的名称
- 每个消息(Message)都具有一个由系统分配或者客户端指定唯一ID
- 每个Stream中的消费组(Consumer_Group)具有唯一名称
- 每个消费组(Consumer_Group)中的消费者(Consumer)具有唯一名称
2.3 消息ID
Stream的消息ID可以由服务端自动生成,也可以由客户端传入,如下图是自动生成的结构:
系统自动生成的规则
<millisecondsTime>-<sequenceNumber>
millisecondsTime指的是Redis节点服务器的本地时间,如果存在当前的毫秒时间戳比以前已经存在的数据的时间戳小的话(本地时间钟后跳),那么系统将会采用以前相同的毫秒创建新的ID。
sequenceNumber指的是序列号,在相同的millisecondsTime毫秒下,序列号从0开始递增,序列号是64位长度,理论上在统一毫秒内生成的数据量无法到达这个级别,因此不用担心sequenceNumber会不够用。
客户端显示传入规则
Redis对于ID有强制要求,格式必须是-,最小ID为0-1,并且后续ID不能小于前一个ID
2.4 消息内容
Stream的消息内容,也就是图中的Message Content它的结构类似Hash结构,以key-value的形式存在。
3、Stream指令
3.1 指令汇总
Stream的指令根据可以分为两类,分别是消息队列相关指令,消费组相关指令。
消息队列相关指令:
指令名称 | 指令作用 |
---|---|
XADD | 添加消息到队列末尾 |
XTRIM | 限制Stream的长度,如果已经超长会进行截取 |
XDEL | 删除消息 |
XLEN | 获取Strea |