目录
Redis Stream 是 Redis 5.0 版本新增加的数据结构。
Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。
简单来说发布订阅 (pub/sub) 可以分发消息,但无法记录历史消息。
而 Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。
Redis Stream 的结构如下所示,它有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的 ID 和对应的内容:
每个 Stream 都有唯一的名称,它就是 Redis 的 key,在我们首次使用 xadd 指令追加消息时自动创建。
上图解析:
- Consumer Group :消费组,使用 XGROUP CREATE 命令创建,一个消费组有多个消费者(Consumer)。
- last_delivered_id :游标,每个消费组会有个游标 last_delivered_id,任意一个消费者读取了消息都会使游标 last_delivered_id 往前移动。
- pending_ids :消费者(Consumer)的状态变量,作用是维护消费者的未确认的 id。 pending_ids 记录了当前已经被客户端读取的消息,但是还没有 ack (Acknowledge character:确认字符)。
XADD
使用 XADD 向队列添加消息,如果指定的队列不存在,则创建一个队列,XADD 语法格式:
XADD key ID field value [field value ...]
- key :队列名称,如果不存在就创建
- ID :消息 id,我们使用 * 表示由 redis 生成,可以自定义,但是要自己保证递增性。
- field value : 记录。
xdel和xlength就不多介绍了,下面来介绍一下xtrim。
XTRIM
xtrim通过驱逐较旧的条目(具有较低ID的条目)来修剪流。
可以使用以下策略之一对流进行修剪:
MAXLEN
:只要流的长度超过指定的threshold
,threshold
就逐出条目,其中是一个正整数。MINID
:逐出ID低于的条目threshold
,其中threshold
是流ID。
例如,这会将流修剪为恰好最新的1000个项目:
XTRIM mystream MAXLEN 1000
而在此示例中,所有ID低于649085820-0的条目都将被驱逐:
XTRIM mystream MINID 649085820
默认情况下,或者在提供了可选参数时,该命令将执行精确的修整。
根据策略,精确的修整意味着:
MAXLEN
:修剪的流的长度将恰好是其原始长度和指定长度之间的最小值threshold
。MINID
:流中最早的ID恰好是其原始最早ID与指定值之间的最小值threshold
。
XREAD
使用 XREAD 以阻塞或非阻塞方式获取消息列表 ,语法格式:
XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] id [id ...]
- count :数量
- milliseconds :可选,阻塞毫秒数,没有设置就是非阻塞模式
- key :队列名
- id :消息 ID
有时在阻塞时,我们只希望接收从阻塞那一刻起通过xadd添加到流中的条目。在这种情况下,我们对已添加条目的历史记录不感兴趣。这种情况下,我们就要使用$
上面我们去取从阻塞那一刻开始添加到流中的数据。
XGROUP
使用此命令以便管理与流数据结构关联的使用者组,您可以:
- 创建与流关联的新消费者组。
- 消灭一个消费群体。
- 从消费者组中删除特定的消费者。
- 将使用者组上次交付的ID设置为其他名称。
要创建新的消费者组,请使用以下形式:
XGROUP CREATE mystream consumer-group-name $
最后一个参数是流中要考虑已交付的最后一项的ID。在上述情况下,我们使用特殊ID'$'(这意味着:流中最后一项的ID)。在这种情况下,从该消费者组中获取数据的消费者只会看到新元素到达流中。
相反,如果您希望使用者获取整个流历史记录,请使用零作为使用者组的起始ID:
XGROUP CREATE mystream consumer-group-name 0
当然,也可以使用任何其他有效的ID。如果指定的使用者组已经存在,该命令将返回-BUSYGROUP
错误。否则,执行操作并返回OK。可以与给定流关联的消费者组的数量没有硬性限制。
如果创建组时指定的流不存在,将返回错误。您可以使用可选的MKSTREAM
子命令作为后面的最后一个参数,ID
以自动创建流(如果不存在)。请注意,如果以这种方式创建流,则其长度将为0:
XGROUP CREATE mystream consumer-group-name $ MKSTREAM
使用以下形式可以完全销毁一个消费者组:
XGROUP DESTROY mystream consumer-group-name
即使有活动的使用者和待处理的消息,使用者组也将被销毁,因此请确保仅在确实需要时才调用此命令。
每当某个命令提及新的消费者名称时,都会自动创建消费者组中的消费者。也可以使用以下形式显式创建它们:
XGROUP CREATECONSUMER mystream consumer-group-name myconsumer123
要将给定的消费者从消费者组中删除,可以使用以下形式:
XGROUP DELCONSUMER mystream consumer-group-name myconsumer123
有时,删除旧的消费者可能有用,因为它们不再使用了。此表单返回使用者在被删除之前所拥有的待处理消息数。
最后,可以使用SETID
子命令设置下一条要传递的消息 。通常,在创建使用者时将下一个ID设置为最后一个参数XGROUP CREATE
。但是,使用此表单以后可以修改下一个ID,而无需再次删除和创建使用者组。例如,如果您希望使用者组中的使用者重新处理流中的所有消息,则可以将其下一个ID设置为0:
XGROUP SETID mystream consumer-group-name 0
XREADGROUP GROUP
使用 XREADGROUP GROUP 读取消费组中的消息,语法格式:
XREADGROUP GROUP group consumer [COUNT count] [BLOCK milliseconds] [NOACK] STREAMS key [key ...] ID [ID ...]
- group :消费组名
- consumer :消费者名。
- count : 读取数量。
- milliseconds : 阻塞毫秒数。
- key : 队列名。
- ID : 消息 ID。
XREADGROUP GROUP consumer-group-name consumer-name COUNT 1 STREAMS mystream >