【etcd】Txn 与并发语义:compare/mod 与 Jepsen 边界
内容提要
本文介绍etcd v3.5.33中Txn事务的实现机制,包括只读与写事务路径、compare操作(MOD/CREATE/VERSION等)、MVCC可见性及嵌套事务处理。同时分析Jepsen测试边界:KV多键事务在3.4.3中通过严格可串行化检验,但Lease锁因时钟分区问题不安全,需配合fencing机制使用。最后提供并发场景速查表,强调Txn用于条件更新和锁保护,避免无Lease永久key等误区。
延伸解读
Txn 并非万能:区分 KV 事务与 Lease 锁
文章明确指出,Jepsen 对 etcd 3.4.3 的测试中,多 key KV Txn 通过了严格可串行化检验,但 Lease 锁在时钟分区等场景下不安全。因此,不能将“使用 Txn”等同于“获得可串行化协调原语”。Lease 锁需要配合 fencing 机制(如使用 ModRevision 作为 token)才能保证安全。
compare 的典型用途与 fencing 惯用法
compare 支持 VALUE、CREATE、MOD、VERSION、LEASE 等目标,常用于条件更新、乐观锁和选主。文章特别强调 fencing 惯用法:锁 Txn 成功后获取 Header.Revision 或 key 的 ModRevision 作为 token,写资源时用 Compare(ModRevision("<resource>"), "<", token) 拒绝过期持有者的写入。这是应用层协议,etcd 并不自动提供锁语义。
写 Txn 的原子性与性能注意点
etcd 的写 Txn 通过单条 Raft 日志实现原子 apply,无跨 key 锁表,依赖 Raft 全序和单 store 写者。但 compare 失败时仍会占用一条日志 entry,revision 可能不变。嵌套 Txn 的 compare 成本线性于 compare 次数乘以 range 宽度,源码 TODO 提到 range 分块优化,使用时需注意性能。
Q&A
etcd 的 Txn 事务在 API 层有哪些路径?
etcd 的 Txn 在 API 层分为只读 Txn 和写 Txn 两条路径。只读 Txn 的 Success/Failure 仅包含 RequestRange,默认走 linearizableReadNotify → doSerialize → applyV3Base.Txn,不经过 propose;如果所有 Range 带 Serializable: true,则跳过 ReadIndex。写 Txn 包含 Put/DeleteRange/嵌套写,通过 raftRequest(Txn) 发送单条 Raft entry 并 apply。
etcd 的 compare 操作支持哪些目标字段?
etcd 的 compare 操作支持 VALUE、CREATE、MOD、VERSION 和 LEASE 五种目标字段。VALUE 比较 value 的字节序,CREATE 比较 CreateRevision,MOD 比较 ModRevision,VERSION 比较 Version,LEASE 比较绑定的租约 ID。
etcd 中如何使用 ModRevision 实现 fencing 机制?
在 etcd 中,使用 ModRevision 实现 fencing 的惯用法是:锁 Txn 成功后,取 Header.Revision 或 key 的 ModRevision 作为 token;写资源时,使用 Compare(ModRevision("<resource>"), "<", token) 来拒绝 stale holder 的写入。这是应用层协议,不是 etcd 自动提供的锁语义。
etcd 的 Txn 事务如何保证原子性?
etcd 的 Txn 事务通过 Raft 日志全序和单 store 写者保证原子 apply。写 Txn 会作为单条 Raft entry 提交,apply 时在单个写事务中执行 Success/Failure 分支中的操作,如果写失败会 panic,确保写 Txn 不可部分成功。
Jepsen 测试对 etcd 3.4.3 的结论是什么?
Jepsen 测试对 etcd 3.4.3 的结论是:KV 读/写和多 key Txn 在默认线性一致读路径下通过 strict-serializable 检查;--serializable 读允许 stale,与文档一致;Lease 锁/会话在时钟和分区组合下不安全;corrupt-check 与 Watch 在特定配置下存在竞态。
etcd 中选主或抢锁应该使用什么机制?
etcd 中选主或抢锁应该使用 Txn + CREATE=0 或 MOD 比较,并配合 Lease 使用。应避免使用无 Lease 的永久 key。
etcd 的 Txn 与 TiKV 的 Percolator 事务模型有何不同?
etcd 的 Txn 是单 Raft 组上的轻量 CAS 批,没有分布式锁服务,也没有 GC 事务 record;而 TiKV 的 Percolator 是两阶段提交,有跨 key 锁表和分布式事务支持。