第19章 事务

沿MULTI、命令入队、WATCH乐观锁、EXEC和DISCARD判断Redis事务的ACID边界 覆盖5个正式节点,并以Redis 3.0源码、故障和恢复对账验收。

学习目标

  • 能说明 MULTI/EXEC 的排队执行
  • 能解释 WATCH 乐观锁的工作原理
  • 能指出 Redis 事务不支持回滚的边界

为什么从“MULTI/WATCH状态机台”开始

第19章 事务的核心任务是沿MULTI、命令入队、WATCH乐观锁、EXEC和DISCARD判断Redis事务的ACID边界。命令返回值只暴露外层合同;实现解释还必须连接内存结构、写入与读取路径、事件顺序以及失败后的旧状态回收。MULTI/WATCH状态机台把这些关系放进同一条可复位轨迹。

先写预测:当WATCH版本由“排队后变化”进入“执行后变化”时,哪个可观察状态最先变化?再规定什么结果会推翻当前解释。交互中的分数只表达透明因果方向,不冒充真实Redis测量。

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

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

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

本章术语与源码合同

第19章 事务必须守住“入队顺序确定,WATCH键变化使EXEC中止,执行期命令错误按Redis语义返回而非自动回滚”。观察同时记录MULTI/WATCH状态机台一致率与命令错误分叉风险;只有结构快照、函数入口、运行结果和故障反例互相一致,才接受实现结论。

⚡ MULTI / EXEC / WATCH 事务机制
命令队列 + WATCH 乐观锁(状态:空闲WATCH counterversion = 1 (未被修改)命令队列(0 条)空(MULTI 后入队的命令在这里等待)EXEC 结果尚未执行
Redis 事务不支持回滚:EXEC 时某条命令失败,其余命令照常执行。WATCH 实现乐观锁——EXEC 前检查被监视键版本,被修改则整体放弃,客户端重试即可。多命令原子性要求高时优先用 Lua 脚本。
操作日志
  1. 1.事务:MULTI 后命令入队不执行;EXEC 一次性顺序执行。WATCH 监视键,被改则放弃。

作者目录逐项深读

事务的实现

四级证据 1/5。 MULTI后普通命令按顺序进入队列,EXEC才依次执行;事务期间连接状态阻止命令被其他客户端插入。本节点用“事务的实现”作观察点,执行rg 'multiCommand|execCommand|watchForKey|touchWatchedKey' src/multi.c或等价源码探针,保存版本、输入、前后状态和能推翻解释的反例。

验证事务的实现时,先预测WATCH版本从“排队后变化”切到“执行后变化”会改变哪个字段、偏移、文件或消息;再固定命令错误做一次对照。若故障注入没有破坏“入队顺序确定,WATCH键变化使EXEC中止,执行期命令错误按Redis语义返回而非自动回滚”,就撤回当前解释而不是补写故事。

WATCH命令的实现

四级证据 2/5。 WATCH把客户端登记到键的监视集合;键被修改时客户端标记dirty CAS,EXEC返回空结果并放弃队列。本节点用“WATCH命令的实现”作观察点,执行rg 'multiCommand|execCommand|watchForKey|touchWatchedKey' src/multi.c或等价源码探针,保存版本、输入、前后状态和能推翻解释的反例。

验证WATCH命令的实现时,先预测WATCH版本从“排队后变化”切到“执行后变化”会改变哪个字段、偏移、文件或消息;再固定命令错误做一次对照。若故障注入没有破坏“入队顺序确定,WATCH键变化使EXEC中止,执行期命令错误按Redis语义返回而非自动回滚”,就撤回当前解释而不是补写故事。

事务的ACID性质

四级证据 3/5。 Redis事务保证命令顺序和执行期间不被穿插,但执行期错误不会自动撤销此前命令;持久性取决于持久化配置。本节点用“事务的ACID性质”作观察点,执行rg 'multiCommand|execCommand|watchForKey|touchWatchedKey' src/multi.c或等价源码探针,保存版本、输入、前后状态和能推翻解释的反例。

验证事务的ACID性质时,先预测WATCH版本从“排队后变化”切到“执行后变化”会改变哪个字段、偏移、文件或消息;再固定命令错误做一次对照。若故障注入没有破坏“入队顺序确定,WATCH键变化使EXEC中止,执行期命令错误按Redis语义返回而非自动回滚”,就撤回当前解释而不是补写故事。

重点回顾

四级证据 4/5。 第19章 事务的回顾要重新证明“入队顺序确定,WATCH键变化使EXEC中止,执行期命令错误按Redis语义返回而非自动回滚”,并用同一输入比较结构前态、变更轨迹、故障首错与恢复后态

验证重点回顾时,先预测WATCH版本从“排队后变化”切到“执行后变化”会改变哪个字段、偏移、文件或消息;再固定命令错误做一次对照。若故障注入没有破坏“入队顺序确定,WATCH键变化使EXEC中止,执行期命令错误按Redis语义返回而非自动回滚”,就撤回当前解释而不是补写故事。

参考资料

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

验证参考资料时,先预测WATCH版本从“排队后变化”切到“执行后变化”会改变哪个字段、偏移、文件或消息;再固定命令错误做一次对照。若故障注入没有破坏“入队顺序确定,WATCH键变化使EXEC中止,执行期命令错误按Redis语义返回而非自动回滚”,就撤回当前解释而不是补写故事。

最小源码与运行切片

+git clone --branch 3.0 --depth 1 https://github.com/redis/redis.git redis-3.0
+cd redis-3.0
+rg 'multiCommand|execCommand|watchForKey|touchWatchedKey' src/multi.c

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

unit: rdi-19-transaction
source_file: multi.c
axis_a: "WATCH版本"
axis_b: "命令错误"
fault: "把Redis事务描述成遇错自动回滚,忽略EXEC返回逐命令错误的语义"
invariant: "入队顺序确定,WATCH键变化使EXEC中止,执行期命令错误按Redis语义返回而非自动回滚"
replay: same_version_same_input

三个必须主动触发的误区

误区 1

现象 → EXEC 后才发现失败 原因 → 部分命令已生效 修法 → 入队前校验命令合法性

误区 2

现象 → 忘 WATCH 就改共享键 原因 → 并发修改丢失 修法 → 共享键先 WATCH 再事务

误区 3

现象 → 长事务阻塞其他客户端 原因 → 单线程排队等待 修法 → 事务保持短小,大操作拆批

小结

  • MULTI、EXEC 包裹命令队列
  • WATCH 实现乐观锁
  • 事务不支持回滚
  • 队列化保证顺序执行
  • 错误命令在执行时暴露

练习、答案与节点验证

练习

问题 1: Redis 事务为什么不支持回滚?

问题 2: WATCH 如何实现乐观锁?

问题 3: 用 WATCH+MULTI 实现库存扣减防超卖。(独立实现)

术语复核与本章回顾

完成第19章 事务意味着能从multi.c解释沿MULTI、命令入队、WATCH乐观锁、EXEC和DISCARD判断Redis事务的ACID边界,能运行章专属状态实验,能制造反例并在复位后证明旧状态没有残留。

资料与写作方式声明

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

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

讨论

评论区加载中…