第18章 发布与订阅

追踪频道字典、模式链表、订阅状态和PUBLISH扇出,并明确Pub/Sub不持久化消息 覆盖6个正式节点,并以Redis 3.0源码、故障和恢复对账验收。

学习目标

  • 能区分频道与模式两种订阅
  • 能说明消息即发即弃的特性
  • 能判断 pub/sub 与 Stream 的适用场景

为什么从“频道与模式扇出台”开始

第18章 发布与订阅的核心任务是追踪频道字典、模式链表、订阅状态和PUBLISH扇出,并明确Pub/Sub不持久化消息。命令返回值只暴露外层合同;实现解释还必须连接内存结构、写入与读取路径、事件顺序以及失败后的旧状态回收。频道与模式扇出台把这些关系放进同一条可复位轨迹。

先写预测:当订阅类型由“模式”进入“两者重叠”时,哪个可观察状态最先变化?再规定什么结果会推翻当前解释。交互中的分数只表达透明因果方向,不冒充真实Redis测量。

来源、版次与独立重写边界

黄健宏作者读者服务页确认正式出版新版以Redis 3.0为源码基线,列出4部分、24章及完整小节,并链接Redis 3.0中文注释源码。本课程据此映射24个正式单元、145个目录节点,另设学习地图和总复习;未取得出版正文授权,目录只界定范围,不宣称复现原书正文。

本章字段与控制流由Redis官方3.0源码:pubsub.c和作者注释源码交叉核对;Redis当前持久化文档只用于辨认版本差异。中文解释、图示、交互、实验与答案均为独立教学重写,不把目录页或代码仓库许可证误报为原书许可证。

本章术语与源码合同

第18章 发布与订阅必须守住“订阅与退订更新双向关系,发送只到当前匹配客户端,断线消息不被错误承诺可恢复”。观察同时记录频道与模式扇出台一致率与连接状态分叉风险;只有结构快照、函数入口、运行结果和故障反例互相一致,才接受实现结论。

⚡ 发布订阅消息传递
发布者 → 频道/模式 → 订阅者发布者频道newsSUB#1news⬇ 接收SUB#2news⬇ 接收SUB#3sportsSUB#4tech.*
最近消息
暂无发布(消息即发即弃,不持久化)
操作日志
  1. 1.发布订阅:PUBLISH 向频道广播,SUBSCRIBE/PSUBSCRIBE 订阅。消息即发即弃,无订阅者则丢弃。

作者目录逐项深读

频道的订阅与退订

四级证据 1/6。 服务器频道字典把频道映射到客户端链表,客户端也保存订阅集合;订阅与退订要更新双向关系。本节点用“频道的订阅与退订”作观察点,执行rg 'pubsubSubscribe|pubsubUnsubscribe|pubsubPublishMessage' src/pubsub.c或等价源码探针,保存版本、输入、前后状态和能推翻解释的反例。

验证频道的订阅与退订时,先预测订阅类型从“模式”切到“两者重叠”会改变哪个字段、偏移、文件或消息;再固定连接状态做一次对照。若故障注入没有破坏“订阅与退订更新双向关系,发送只到当前匹配客户端,断线消息不被错误承诺可恢复”,就撤回当前解释而不是补写故事。

模式的订阅与退订

四级证据 2/6。 模式订阅保存在独立链表,发布时按glob规则匹配;同一客户端可能因频道和模式各收到一次。本节点用“模式的订阅与退订”作观察点,执行rg 'pubsubSubscribe|pubsubUnsubscribe|pubsubPublishMessage' src/pubsub.c或等价源码探针,保存版本、输入、前后状态和能推翻解释的反例。

验证模式的订阅与退订时,先预测订阅类型从“模式”切到“两者重叠”会改变哪个字段、偏移、文件或消息;再固定连接状态做一次对照。若故障注入没有破坏“订阅与退订更新双向关系,发送只到当前匹配客户端,断线消息不被错误承诺可恢复”,就撤回当前解释而不是补写故事。

发送消息

四级证据 3/6。 PUBLISH遍历精确频道订阅者并扫描匹配模式,返回收到消息的客户端数量,但不保存消息。本节点用“发送消息”作观察点,执行rg 'pubsubSubscribe|pubsubUnsubscribe|pubsubPublishMessage' src/pubsub.c或等价源码探针,保存版本、输入、前后状态和能推翻解释的反例。

验证发送消息时,先预测订阅类型从“模式”切到“两者重叠”会改变哪个字段、偏移、文件或消息;再固定连接状态做一次对照。若故障注入没有破坏“订阅与退订更新双向关系,发送只到当前匹配客户端,断线消息不被错误承诺可恢复”,就撤回当前解释而不是补写故事。

查看订阅信息

四级证据 4/6。 PUBSUB子命令读取当前频道、模式和订阅者统计,它是瞬时状态而非历史投递记录。本节点用“查看订阅信息”作观察点,执行rg 'pubsubSubscribe|pubsubUnsubscribe|pubsubPublishMessage' src/pubsub.c或等价源码探针,保存版本、输入、前后状态和能推翻解释的反例。

验证查看订阅信息时,先预测订阅类型从“模式”切到“两者重叠”会改变哪个字段、偏移、文件或消息;再固定连接状态做一次对照。若故障注入没有破坏“订阅与退订更新双向关系,发送只到当前匹配客户端,断线消息不被错误承诺可恢复”,就撤回当前解释而不是补写故事。

重点回顾

四级证据 5/6。 第18章 发布与订阅的回顾要重新证明“订阅与退订更新双向关系,发送只到当前匹配客户端,断线消息不被错误承诺可恢复”,并用同一输入比较结构前态、变更轨迹、故障首错与恢复后态

验证重点回顾时,先预测订阅类型从“模式”切到“两者重叠”会改变哪个字段、偏移、文件或消息;再固定连接状态做一次对照。若故障注入没有破坏“订阅与退订更新双向关系,发送只到当前匹配客户端,断线消息不被错误承诺可恢复”,就撤回当前解释而不是补写故事。

参考资料

四级证据 6/6。 本章目录范围由作者页面确认,字段和控制流回到Redis 3.0的pubsub.c与黄健宏注释源码核验;新版资料只承担差异说明

验证参考资料时,先预测订阅类型从“模式”切到“两者重叠”会改变哪个字段、偏移、文件或消息;再固定连接状态做一次对照。若故障注入没有破坏“订阅与退订更新双向关系,发送只到当前匹配客户端,断线消息不被错误承诺可恢复”,就撤回当前解释而不是补写故事。

最小源码与运行切片

+git clone --branch 3.0 --depth 1 https://github.com/redis/redis.git redis-3.0
+cd redis-3.0
+rg 'pubsubSubscribe|pubsubUnsubscribe|pubsubPublishMessage' src/pubsub.c

该切片固定Redis 3.0分支、编译器、配置、数据集和命令序列;先保存结构或函数位置,再运行隔离实例。任何持久化损坏、断线、故障转移、大键或高流量实验都必须使用临时数据并规定CPU、内存、磁盘、延迟和停止上限。

unit: rdi-18-pubsub
source_file: pubsub.c
axis_a: "订阅类型"
axis_b: "连接状态"
fault: "把Pub/Sub误当持久队列,向断线订阅者承诺补发历史消息"
invariant: "订阅与退订更新双向关系,发送只到当前匹配客户端,断线消息不被错误承诺可恢复"
replay: same_version_same_input

三个必须主动触发的误区

误区 1

现象 → 当可靠消息队列用 原因 → 断线消息全部丢失 修法 → 可靠投递换 Stream

误区 2

现象 → 模式订阅滥用 原因 → 匹配开销随模式数涨 修法 → 控制模式数量与复杂度

误区 3

现象 → 发布后不验证送达 原因 → 静默丢失无人知 修法 → 关键路径加确认机制

小结

  • 频道与模式两种订阅方式
  • 消息即发即弃不持久
  • 发送者不知道订阅者存在
  • 适合实时通知类场景
  • 可靠性要求高时选 Stream

练习、答案与节点验证

练习

问题 1: pub/sub 消息为什么不持久?

问题 2: 模式订阅相比频道订阅的代价是什么?

问题 3: 为一个库存告警场景选择 pub/sub 或 Stream 并说明理由。(独立实现)

术语复核与本章回顾

完成第18章 发布与订阅意味着能从pubsub.c解释追踪频道字典、模式链表、订阅状态和PUBLISH扇出,并明确Pub/Sub不持久化消息,能运行章专属状态实验,能制造反例并在复位后证明旧状态没有残留。

资料与写作方式声明

本章以黄健宏《Redis设计与实现》(机械工业出版社)权威目录界定学习范围,并结合正文列出的技术资料独立重写;不宣称复现原书正文,也不沿用原作表述。

原作版权归作者与出版社所有;本站原创教学结构与表述仅供学习交流。

讨论

评论区加载中…