消息队列:Stream

问题1:Stream工作过程如何?

答:Stream有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的ID和对应的内容。消息是持久化的,Redis重启后内容还在。

每个Stream都有唯一的名称,名称就是Redis的key,在首次使用xadd指令追加消息时自动创建

每个Stream都可以挂多个消费组,每个消费组会有个游标last_delivered_id在Stream 数组之上往前移动,表示当前消费组已经消费到哪条消息了。每个消费组都有一个Stream内唯一的名称,消费组不会自动创建,它需要单独的指令xgroup create进行创建,需要指定从Stream的某个消息ID开始消费,这个ID用来初始化last_delivered_id变量。

每个消费组的状态都是独立的,相互不受影响。也就是说同一 Stream内部的消息会被每个消费组都消费到。

同一个消费组可以挂接多个消费者,这些消费者之间是竞争关系,任意一个消费者读取了消息都会使游标last_delivered_id往前移动。每个消费者有一个组内唯一名称。

消费者内部会有个状态变量pending_ids,它记录了当前已经被客户端读取的消息,但是还没有ack。如果客户端没有ack,这个变量里面的消息ID会越来越多,一旦某个消息被ack,它就开始减少。这个pending_ids变量被称之为PEL,也就是Pending Entries List。

问题2:消息ID格式是什么?

答:timestampInMillis-sequence。可以由服务器自动生成,也可以由客户端自己指定,但是形式必须是整数-整数,而且必须是后面加入的消息的ID要大于前面的消息ID。

问题3:消息内容格式是什么?

答:键值对形式。

问题4:指令有哪些?

答:

xadd追加消息

xdel删除消息,这里的删除仅仅是设置了标志位,不影响消息总长度

xrange获取消息列表,会自动过滤已经删除的消息

xlen消息长度

del删除 Stream

xgroup create指令创建消费组,需要传递起始消息ID参数用来初始化last_delivered_id变量。

xreadgroup指令可以进行消费组的组内消费,需要提供消费组名称、消费者名称和起始消息ID。它同xread一样,也可以阻塞等待新消息。读到新消息后,对应的消息 ID 就会进入消费者的 PEL结构里,客户端处理完毕后使用xack指令通知服务器,本条消息已经处理完毕,该消息 ID 就会从PEL中移除。

问题5:xread指令有何特别之处?

答:xread可以将Stream当做一个普通的列表list,该Stream所有的消费组全部忽略不见。

Xread会返回消息ID,下次继续调用xread 时,将上次返回的最后一个消息ID作为参数传递进去,就可以继续消费后续的消息。

问题6:Stream消息太多如何处理?

答:Redis提供了一个定长Stream功能。在xadd指令提供一个定长长度maxlen,就可以将老的消息干掉,确保最多不超过指定长度。

问题7:如果客户端忘记ACK,会造成什么后果?

答:如果消费者收到了消息处理完了但是没有回复ack,就会导致PEL列表不断增长,进而导致PEL占用的内存就会放大。

问题8:消费者如何确保客户端收到消息?

答:客户端断开连接又重新连上之后,可以再次收到PEL中的消息ID列表。不过此时xreadgroup的起始消息ID不能为参数,而必须是任意有效的消息ID,一般将参数设为 0-0来表示读取所有的 PEL消息以及自last_delivered_id之后的新消息。

问题9:Stream如何实现高可用?

答:Stream高可用是建立主从复制基础上的,也就是说在 Sentinel和 Cluster集群环境下Stream是可以支持高可用的。鉴于 Redis指令复制是异步的,在failover发生时Redis可能会丢失极小部分数据,这点Redis的其它数据结构也是一样的。

发布了167 篇原创文章 · 获赞 10 · 访问量 9万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章