Redis 8.6新特性介绍(2):流的幂等生产机制

Tip

观看本文的视频版本:https://www.bilibili.com/video/BV1NVNuzPEQ1/

在Redis 8.6之前,如果流的生产者客户端在接收到XADD命令的返回值之前掉线了,那么它将无法确定命令发送的消息是否成功,而处理这种情况的通常做法是再次发送相同的消息。

但这样一来,如果服务器之前已经接收到该客户端发送的消息了,只是客户端并未成功接收到服务器返回的回复(消息的ID),那么重复发送相同消息将导致服务器包含两条重复的消息。


+--------+                           +--------+
|        | -- XADD s * "k1" "v1" --> |        |
|        |      X-- msg_id_1 ------- |        |
| Client |                           | Server |
|        | -- XADD s * "k1" "v1" --> |        |
|        | <------- msg_id_2 ------- |        |
+--------+                           +--------+

图示:重复发送相同消息的情况


为了解决这个问题,Redis 8.6为流添加了幂等生产机制,以此来保证“同一条消息最多只投递一次”。为了启用这种机制,用户需要在执行XADD命令的时候,使用可选的IDMP选项或是IDMPAUTO选项,并提供相应的生产者标识符(pid)和幂等标识符(iid):

XADD key [IDMP pid iid | IDMPAUTO pid]
         <*|id> field value [field value] [...]

注意

IDMPAUTO选项可以根据消息的内容自动生成幂等标识符,但由于该选项对于内容相同的消息总是生成相同的幂等标识符,所以如果你确实有需要发送相同的消息,那么请务必使用IDMP选项而不是IDMPAUTO选项。

与此对应的是,Redis服务器在每次执行带IDMP/IDMPAUTO选项的XADD命令之后,会将被执行命令的pid和iid存储起来,并在之后每次收到带IDMP/IDMPAUTO选项的XADD命令时,检查给定的(pid, iid)对是否存在:

  • 如果存在则表示该消息最近已经接收过,服务器将返回对应的已存在消息的ID为结果;

  • 如果不存在则表示该消息应该是一条新消息,服务器将为其创建并返回新ID为结果。


+--------+                                          +--------+
|        | -- XADD s IDMP 10086 123 * "k1" "v1" --> |        |
|        |                     X-- msg_id_1 ------- |        |
| Client |                                          | Server | (pid, iid):
|        | -- XADD s IDMP 10086 123 * "k1" "v1" --> |        | (10086, 123)->msg_id_1
|        | <--------------- msg_id_1 -------------- |        |
+--------+                                          +--------+

图示:未重复发送消息的情况


最后,为了控制被存储的(pid, iid)对数量,Redis 8.6还引入了新的设置命令:

XCFGSET key [IDMP-DURATION seconds] [IDMP-MAXSIZE num]

其中IDMP-DURATION用于设置每个iid的最长存储秒数,而IDMP-MAXSIZE则用于设置每个客户端(也即是对应每个pid)能够保存的最近iid数量。

好的,关于Redis 8.6版本新引入的流的幂等生产机制今天就介绍到这里,感谢大家的观看和阅读~

喜欢这篇博文/这个视频的话欢迎大家给我点赞和关注,谢谢!

黄健宏
2026.3.15