Redis Stream使用要点

本文详细介绍了Redis Stream的使用,包括信息条目ID、三种应用模式(时序数据库、日志读取、使用者组)以及消息的删除和获取。重点讨论了使用者组模式下的待确认信息管理,并提供了使用场景的总结,如缓存和消息分发系统。

本文的适用于Redis6.0。

一、流信息条目id

流(stream)中信息条目的ID必须是单调增的,为此,redis采用时间戳+自增id这种方式来保证,并且这两个数都是64bit,不会有溢出问题,最后一点,redis在增加信息条目时会检查当前id与上一条目的id,自动纠正错误的情况,一定要保证后面的id比前面大。

一个流中信息条目的ID必须是单调增的,这是流的基础,所以本文首先强调一下。

几个特殊的ID:

-,+:最小和最大可能出现的Id,也就是“0-1”和“最大整数-最大整数(64位)”

$:当前流中最大的id,可用于将要到来的信息

>:用于XREADGROUP命令中,表示迄今还没有发送给组中使用者的信息

*:用于XADD命令中,让系统自动生成id

*:用于XADD命令中,让系统自动生成id

二、三种应用模式

在官方文档中,redis提到有三种工作模式:

时序数据库模式

XRANGE用于已知上下限,查询出结果,非阻塞,因此有可能返回空。XRANGE命令没什么特别的地方(指采用其他数据结构也能完成类似功能),就是查询信息而已。

日志文件读取模式

XREAD有阻塞和非阻塞两种模式,用于从已知下限开始查询到最大ID,它可以从多个流读取(而XRANGE只能从一个流读取)

非阻塞模式:基本与XRANGE功能相同。

阻塞模式: 比较有用的是等待(阻塞)读取信息,一旦信息产生者发出消息,就取消阻塞,带结果退出了,此时如果有多个用户同时进行这种操作,每个用户都能得到信息(信息是Fan out),类似于PUB/SUB机制。但需要注意的时,subscribe会一直保持侦听状态(阻塞),所以会不断收到来自channel的消息,而XREAD是一次性侦听,只要有满足条件的信息到来,它就退出了。

可以看出,XREAD可以用作消息通知,消息源可以是多个,但不如pub/sub简单。

  • 可以查询某时刻之后是否有通知
  • 如果有新通知,告述我(一次性)
  • 如果需要不断接收新消息,首次指定起始id为$(当前最大id),下次id指定为上次返回的最大的id,不断调用XREAD block …

使用者组模式

这是三种模式中最复杂的。为理解它的机制,先大致画一下命令可能用到的流的结构。

每个流有一个last_generated_id(即流中最大的id),它是流条目id自增性的基础,流信息条目采用的是radix tree来存储,为提高存储效率,每个节点存储若干条目。

每个流可以有若干使用者组(consumer group),每个使用者则可以有若干使用者(consumer),每个使用者组有一个last_delivered_id(即本组中已发送的最大信息)。使用者组需要显式创建,使用者却是随使用而自动创建(第一次读取到信息时)。

每名使用者有一个pending messages(这里称为待确认信息,即被挂起的,待用户确认已正确收到的信息)列表,它保留了一份信息的拷贝,因此即使流信息条目被删除,这里也会保留到用户ACK为止。由于存在不ACK或不及时ACK的情况,对每一条待确认信息,有idle time(现在时刻减去最后一次发送该条目时刻的毫秒数)和delivered count(总发送的次数),关于待确认信息的管理,见下面的描述。

这种工作模式通常的流程如下:

第一步,以XGROUP CREATE创建用户组。

XGROUP CREATE stream groupname id,该命令执行后,在流中创建一使用者组,并设置此组的last_delivered_id为上面指定的id,由流的last_generated_id与组的last_delivered_id进行比较,就可以确定此组有多少信息应该分发给该组的用户(这里称为待分发信息表,它是计算出来的,并不真的存在,只是为方便)。需要说明的是,使用者组是“属于”某一流的,可以在不同的流中,创建相同名字的使用者组,这就是同一个使用者组从多个流读取信息的办法。

XREADGROUP GROUP groupname consumer [COUNT count][BLOCK milliseconds] [NOACK] STREAMS key [key ...]ID [ID ...]

 其中ID有两种形式:“>”和某一有效ID。

对ID为前者的情况,表示从待分发信息中读取,该命令执行后,待分发信息从流的信息条目表中拷贝一份到使用者的待确定信息表中(无NOACK选项),然后发送,如果此时有两个使用者在等待信息,则第一个加入的使用者会首先得到它想要的信息,如果还有待分发的信息,则第二个加入的使用者会得到信息,如此直到待分发信息为空或者等待的使用者为空,最后更新使用者组的last_ delivered_id(也就意味着更新待分发信息)。

对于ID为后者的情况,表示从该使用者的待确定信息中读取。直接从该使用者的待确定信息中看看是否有满足条件的信息,如有就发送,并更新该条目的idle时间和delivered count。

第三步,XACK确认收到消息。

XACK key group ID [ID ...]

该命令由消息使用者在收到消息后发出,服务器端将该条目信息从待确认信息表中删除。如果在XREADGROUP命令后加上NOACK,则不产生待确认信息(不拷贝),也就不需要此步骤。因此是否需要ACK由具体的应用决定,对于允许信息遗漏的场景,可以添加NOACK,简化应用。

以下是一个简要的流程示意图。

待确认信息(pending messages)的管理

由于存在信息收到后的确认问题,因此实际要考虑的情况比上面的正常流程要多些,比如使用者宕机怎么办,会不会出现所有使用者都不能处理的信息等。

上面说过,每条待确认信息有Idle time和Delivery count两个属性,Idle time由XREADGROUP和XCLAIM命令重置,而Delivery count,由XREADGROUP和XCLAIM命令触发增加,因此,如果发现某条信息的Idle time过大,大概率该使用者已崩溃了。

基本流程如下:

  • 第一步,使用XPENDING命令查看使用者组中待处理信息的idle time和Delivery count。
  • 如果某待处理信息的idle time超出预设,使用XCLAIM回收所有权并赋给其他使用者,注意,此时Idle time会重置,而Delivery count会增加。
  • 如果某待处理信息的Delivery count超出预设,很可能此信息已被多次XCLAIM,本身有缺陷,不会被任何正常使用者处理了,赋给特殊的使用者(管理员之类),进行特殊处理。

作为最后的措施,可以用XGROUP DELCONSUMER stream consumergroup consumer删除某个使用者,其pending message也就随之删除了。

三、消息的删除

有两种方式可以删除流中的信息。

  • 采用XTRIM命令:XTRIM的目标是以某种“策略”来删除信息条目,它以后有可能被扩展,目前只支持MAXLEN选项(XADD命令也支持,因此XADD也有隐含删除功能),优先删除id小的条目,也就是可以产生所谓“定长流”(条目数上限,Redis强烈建议大约上限数)的效果。
  • 采用XDEL命令:这个命令比较好理解,就是删除某条信息。

四、得到流的信息

以下是几个查询流信息的命令,它们都是只“读”的。

  • XINFO 可以得到流信息和流中使用者组信息。
  • XPENDING可以得到流的某一使用者组或者某一使用者的挂起条目(pending messages)的信息
  • XLEN可以得到流所有条目的大小

五、使用场景小结

从上面的描述,可以看出,Redis stream可以用在以下的场景:

  1. 将redis作为缓存,与其他redis应用一样,只是此时数据结构是只增的流式结构,由于id与时间相关且自增,从而可以进行范围(时间、id)读取,范围可以只包括单边(有起点无终点、无启点有终点),进而如果起点是当前最大id的话,就是读取新到的信息。
  2. 以构建使用者组的方式进行读取,此时redis更像一个分发(负载均衡)系统,前端,多个数据源可以将信息发给同一个流,后端,在一个组中的多个使用者(负载承担者)从这个流中读取,如果消息特别重要,不允许无故丢失,就需要加消息收到确认,否则可以不加消息确认。对需要确认的场合,使用者应先读取那些未确认的消息(不管有没有),再读取新信息,并且要有额外的监控进程定期处理那些“dead letter”。

需要说明的是:由于信息的分发是由客户端主动“索取”的结果,面对多个读取命令,redis并不需要分发策略,完全由客户端决定自己所应承担多少“负荷”。

为实用,无论哪种场景,流应定期调用XTRIM MAXLEN来限制总信息长度,以提高性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值