Skip to content

本轮为理论笔记与静态审读,示例、安装命令和验收器均未执行。下文命令用于解释步骤,预期结果不代表本轮实测;“历史验收”仅指此前批次记录。阅读和书面练习不需要启动服务。

etcd revision、事务与配置 CAS ​

三种版本号 ​

前置:已启动实验节点,会读取 JSON。etcd 的 revision 是全局逻辑时钟:一次修改事务统一推进一次 revision;同一事务中多个键的变更可以具有相同 revision。键的 version 是该键自创建以来的修改次数,删除重建后重新计数。create_revision 标记创建时刻,mod_revision 标记最近修改时刻;三者不能混用。

powershell
docker exec showdocs-m4b-etcd-main etcdctl put /course/config initial
docker exec showdocs-m4b-etcd-main etcdctl get /course/config -w json
docker exec showdocs-m4b-etcd-main etcdctl put /course/config changed
docker exec showdocs-m4b-etcd-main etcdctl get /course/config -w json

第二次读时 version 增加,create_revision 不变,mod_revision 增加;header.revision 还可能被别的键推进。不要把 header.revision 作为这个键最近修改的版本。用 get --rev=N 可以读某个历史状态,前提是历史还没有压缩。

原子比较交换 ​

CAS 是 compare-and-swap:比较键的 mod_revision 等于读取时记录的值,成立才写新值。比较与写入作为一次服务端事务执行,两个读到相同版本的写者最多一个成功。修改值即使后来恢复到原字符串,mod_revision 也已经变化,因此比只比较字符串更能检测中间修改。

etcdctl txn 输入依次是比较、成功分支、失败分支,分支之间以空行分隔。不存在的键 mod_revision 为 0,可用于“仅在未创建时写入”。失败分支读回当前值,帮助提示用户冲突;不能把冲突当作自动覆盖许可。

text
mod("/course/config") = "7"

put "/course/config" "new-value"

get "/course/config"

上面的文本是事务输入内容,不是独立 Shell 命令。若要形成完整调用,在仓库根目录创建 UTF-8 文本 examples/etcd/cas.txt,保存该文本并保留分支之间的空行;以下 PowerShell 管道把它送入容器内的 etcdctl 标准输入(本轮不执行):

powershell
Get-Content -Raw -Encoding utf8 examples/etcd/cas.txt | docker exec -i showdocs-m4b-etcd-main etcdctl txn -w json

这里的 7 是演示,必须替换为真实 mod_revision。返回 FAILURE 表示比较未满足,不是事务只执行了一半;JSON 的 succeeded 字段更适合程序判定。成功和失败分支各自也是原子的。不要在同一事务内重复修改同一个键,也不要以多条独立 put 代替多键原子提交。

竞争验收与业务处理 ​

并发更新必须将冲突作为正常业务分支。完整程序在配置应用中。分别运行 get,拿到 revision 后,让两个终端对同一 revision 执行 cas。预期一个退出 0、一个退出 2,最终值是其中一个写者的值。项目验证器使用两个真正并行的子进程发起竞争,并检查退出码集合是 [0,2],不会靠顺序写入伪造竞争结果。

业务可以在冲突后重新读取配置、展示差异并由用户合并,或在操作确实可重算时有限重试。把整个旧配置盲目重发会丢失其他客户端的修改。事务只协调 etcd 内部状态,不会把发邮件、调用外部 API 或写本地文件也变成原子操作;外部副作用需要幂等协议与自己的失败恢复设计。

练习与参考解法 ​

题目:A 读到 blue,B 改为 red 又改回 blue,A 比较 value=blue 可以发现 B 的修改吗?比较哪个字段合适?

提示:分别记录 blue→red→blue 时 value 与 mod_revision 是否回到初值。

参考答案与边界

只比较 value 无法发现这段修改;比较先前读到的 mod_revision 会失败。若业务只关心当前值是否 blue,值比较也可能是正确合同,关键是先明确“是否有中间修改”是否属于业务冲突。不要把所有值比较都说成错误。

资料:官方 API 机制、etcdctl 事务输入格式。

继续阅读