Redis 进阶 06:Pub/Sub 与 Streams

实验基线:Redis 7.4.11,先完成环境准备。除标注为宿主机终端的代码外,Redis 命令在该课指定的 redis-cli 中执行;不复制输出结果作为命令。

学习目标#

区分 Pub/Sub 与 Streams,完成消费组读取、确认和 pending 检查,理解重复投递与幂等处理。

原理:是否需要补消费#

Pub/Sub 是即时广播,离线订阅者收不到此前消息,也没有确认与重放能力。适合允许丢失的通知,不适合作为订单处理唯一链路。

Streams 保存带 ID 的消息序列。消费组将新消息分配给消费者,并用 pending entries list(PEL)跟踪未确认的消息。读取并不等于业务完成,业务成功后才 XACK。再次认领和重试意味着至少一次语义,不能宣称恰好一次处理。

实验:即时广播#

两个客户端均连接 redis-learning。终端 A:

SUBSCRIBE learn:events:notice

终端 B:

PUBLISH learn:events:notice hello

只有 A 已成功订阅时,B 返回订阅者数量 1,A 收到 hello。A 停止订阅后再发布,消息不会为它保留。可按 Ctrl+C 离开订阅模式,随后重新启动 redis-cli。

实验:消费组与新消息#

在普通 redis-cli 中:

UNLINK learn:stream:orders
XGROUP CREATE learn:stream:orders workers 0 MKSTREAM
XADD learn:stream:orders * orderId 42 status paid
XADD learn:stream:orders * orderId 43 status paid
XREADGROUP GROUP workers consumer-A COUNT 1 STREAMS learn:stream:orders >
XPENDING learn:stream:orders workers

预期建组 OK,两个 XADD 返回不同的消息 ID。XREADGROUP 得到第一条订单;把实际返回 ID 记下来,不能把文中的说明文字粘贴为 ID。XPENDING 汇总显示 1 条待确认记录,所属消费者 consumer-A。

消费组创建位置 0 表示从历史起点开始;用 $ 表示从建组时的末尾开始。XREADGROUP 的 > 表示组内尚未投递的新消息,不包括其他消费者 pending 的消息。

实验:确认与故障认领#

业务处理成功后,用上一步真实 ID 替换占位符:

XACK learn:stream:orders workers <实际消息ID>
XPENDING learn:stream:orders workers

预期 XACK 返回 1,pending 数量回到 0;消息仍存在于 Stream,确认不等于删除。

再次读取第二条消息,但故意不确认,等待至少 1 秒:

XREADGROUP GROUP workers consumer-A COUNT 1 STREAMS learn:stream:orders >
XAUTOCLAIM learn:stream:orders workers consumer-B 1000 0-0 COUNT 10
XPENDING learn:stream:orders workers

XAUTOCLAIM 返回下一个扫描游标及被认领的消息;未满 1000 毫秒可能返回空列表,可以稍后重试。此命令在 Redis 6.2 起可用,本系列 7.4.11 支持。B 成功处理后用认领的实际 ID 执行 XACK。

常见错误#

  • 在业务提交前 XACK:处理失败后没有 pending 可供重试。
  • 业务提交后进程崩溃,还没 XACK:消息会再次处理,必须以 orderId 或事件 ID 建立幂等。
  • 只用 > 读取:崩溃消费者的 pending 不会自动变成新消息。
  • 无限保留消息:要设计 MAXLEN/修剪和保留期,但删掉 pending 对应消息可能导致无法重放,需要协调业务恢复窗口。

练习与参考答案#

查看流长度,并解释“确认后为什么长度没变”:

XLEN learn:stream:orders
XRANGE learn:stream:orders - + COUNT 10

长度为 2。XACK 仅清除消费组待确认状态;业务去重记录应在可靠存储中与业务提交协调,不能仅靠一个短 TTL Redis 标记承诺永久幂等。

清理#

XGROUP DESTROY learn:stream:orders workers
UNLINK learn:stream:orders

Pub/Sub 的频道不是存储键,离开订阅即可,无须 DEL 频道。

官方参考#

Streams · XREADGROUP · XAUTOCLAIM · Pub/Sub

学习导航#

上一课:Redis 进阶 05:分布式锁与限流 · 学习目录 · 下一课:Redis 进阶 07:复制、Sentinel 与 Cluster

Redis 进阶 06:Pub/Sub 与 Streams
作者:LcooYa
CC BY-NC-SA 4.0
相关文章
随机文章