前 15 篇把 etcd 生产路径拆到可归因精度:单 Raft 组、WAL/快照、Revision MVCC、bbolt 单写者、Apply 管道、ReadIndex、Watch/watchableStore、Lease/checkpoint、K8s apiserver 耦合、运维升级与五轴排障。选型若再写成「etcd 轻、TiKV 能扩、FDB 最严」,等于把机制丢掉。
本文是终章:用机制排除树收束判断,回收 distributed/39、tikv-htap/18、foundationdb/18 指向的 etcd 协调叶,写明何时不该继续 etcd,列出仍开放的问题,并以 ADR 可粘贴的语言关闭「etcd 生产内核」续作边界。不做跨方案 QPS 或延迟排行榜。
本篇在系列中的位置
篇目 核心内容 第 15 篇 · 排障五轴 Raft/WAL/MVCC/Watch/Lease 口令表 第 16 篇 · 选型收束(终章) 排除树、开放问题、边界关闭 系列目录 全部篇目
版本锚定:etcd v3.5.33(源码 tag
v3.5.33)。TiKV / FoundationDB 对照钉姊妹系列终章版本,不在此重讲 Multi-Raft 或 Unbundled 全书。Kine 等 etcd API 兼容层只写边界一句。
一、机制排除树
排除树每一叶必须回答一个可证伪的机制问题,而不是「看场景」。
flowchart TD
need{"Need strongly consistent\ncoordination KV?"}
need -->|"No"| other["Pick CP store or app-local state\nnot this tree"]
need -->|"Yes"| small{"Data and churn fit\nsingle Raft group quota?"}
small -->|"No"| scale{"Need horizontal shard\nand multi-key TX?"}
scale -->|"Yes, SI OK"| tikv["TiKV Multi-Raft path\nsee tikv-htap/18"]
scale -->|"Yes, strict serializable"| fdb["FoundationDB Unbundled\nsee foundationdb/18"]
scale -->|"No, only bigger cache"| split["Split etcd clusters\nK8s events override"]
small -->|"Yes"| watch{"Watch plus Lease are\nfirst-class product semantics?"}
watch -->|"No"| zk["ZooKeeper or Consul path\nsee distributed/39"]
watch -->|"Yes"| k8s{"Embedded in K8s\ncontrol plane stack?"}
k8s -->|"Yes"| etcdk8s["etcd v3.5.x K8s path\nthis series"]
k8s -->|"No"| staff{"Can staff run five-axis\nops and quota SLO?"}
staff -->|"No"| defer["Do not run etcd yet"]
staff -->|"Yes"| etcdk8s
| 机制判据(问句) | 若「否」 | 倾向 |
|---|---|---|
| 需要强一致协调 KV? | 不必进入本树 | 应用内状态 / 最终一致缓存 |
| 数据量与 churn fit 单 Raft 组 + quota(约 2–8 GB backend)? | 单组会触顶 | TiKV / 分集群 / 非 etcd |
| Watch 有序推送 + Lease TTL 是一等产品语义? | 只要 CAS 或 znode | ZK/Consul 或 FDB Layer |
| 需要跨分片 ACID / PB 扩展? | etcd 不是 OLTP | tikv-htap/18 |
| 需要 strict serializable + Layer? | SI 不够 | foundationdb/18 |
| 团队能按 第 15 篇 五轴值班? | 机制再强也运维不起 | 托管或缓装 |
| K8s 控制面默认栈? | 自研协调 | 仍可能是 etcd,但须单列 ADR |
排除树与 tikv-htap/18、foundationdb/18 互补:姊妹终章先问「数据规模与事务模型」;本篇在「小数据 + Watch/Lease」分支上继续问「单 Raft 组 quota 与五轴运维是否成立」。三棵树应先后走,不应把任一叶当成全局默认答案。
甜区:K8s 控制面或等价协调场景;键空间在 quota 内;写入以元数据为主;强依赖 Watch 从指定 revision 有序追赶 与 Lease 自动删键;团队能 compact/defrag/backup;版本钉 v3.5.33(或发行版声明对齐的 3.5.x patch)。
苦区:把 etcd 当通用 OLTP;单 key/value 逼近 1.5MB;百万 key 级全量 Range;需要 Multi-Raft 吞吐却只想「加 etcd 节点」;无 snapshot 就 member 实验;把 distributed/39 海报 QPS 当选型依据;用 Kine 却假设与原生 Watch 语义完全一致。
何时不该继续 etcd(否证条件)
下列任一成立,排除树上 etcd 叶判负(可写进 ADR):
- backend 持续触顶或
alarm——compact/defrag 仍无法稳住 MVCC 轴(第 12
篇)。
- 写入/churn 需要水平分片——加 voting
member 不提高写吞吐(单 Raft 组上限,第 2
篇)。
- 需要跨 key 分布式事务——Mini-Txn 不是
Percolator/FDB 事务(第 11
篇)。
- Watch
背压已主导可用性——
ErrCompacted恢复成本不可接受且无法调 retention(开放问题 §三)。
- 编制撑不住五轴——故障只能「重启 etcd」
(第 15
篇)。
- 必须 strict serializable 协调——Jepsen
表明 Lease 锁子集不安全 (distributed/53);需
fencing 或换 FDB。
- 误以为 FDB/TiKV 可无缝替换 K8s etcd——控制面 Watch/Lease 运维形态不同(姊妹终章已否;本篇再钉)。
否证触发后应重跑排除树。已上线 POC 不是机制判据:quota 触顶后「都装好了」不能阻止迁 TiKV 或 events 分集群。
二、回收 distributed/39 的 etcd 叶
distributed/39 · KV 存储对比 用架构表对比 etcd/TiKV/FDB,并在 §6–7 给出场景化路径。该文 etcd 叶 停在「协调层海报」——读者知道单 Raft 组与 Watch,但不知道 Raft lag vs apply lag 如何分列、Compaction 如何写进 SLO、K8s apiserver 超时落在哪轴。
| distributed/39 原内容 | 本系列回收位置 | 关闭状态 |
|---|---|---|
| etcd 架构 / MVCC / Watch 概览 | 04–09 篇;50 百科仍保留速览 | 已展开 |
| 性能表(官方引用级) | 本篇 禁止裸吞吐排名;39 表仍作百科 | 分工 |
| §6.1 选 etcd 场景 | 本篇排除树甜区 | 已机制化 |
| §7.1 etcd 局限 | 本篇否证条件 1–4 | 已机制化 |
| 「何时不该用 etcd」列表 | 本篇 §一 + 15 五轴 | 已展开 |
给读完 39 的读者一句口令:
- 「三方海报与架构图」→ 仍看
distributed/39
- 「一次写入卡在哪层、怎么排障」→ 本系列
01–15
- 「该不该留 etcd」→ 本篇排除树
39 不必重写;etcd 叶机制深度由本系列承接,避免 39 膨胀成第二套 16 篇。
三、回收 tikv-htap/18 与 foundationdb/18 的 etcd 叶
tikv-htap/18 与 foundationdb/18 的决策树都在 「数据 < 2GB 且要 Watch/Lease → etcd」 处把读者指向 distributed/39,并写「K8s 控制面不必读 TiKV/FDB 02–15」。当时 etcd 叶悬空:知道不该上 TiKV,不知道 etcd 触顶后的分集群、events override、quota ADR 怎么写。
| 姊妹终章原指针 | 本系列回收 | 关闭状态 |
|---|---|---|
| etcd = 元数据 / 服务发现 | 01 全景;13 K8s;16 排除树 | 已展开 |
| 「不必读 TiKV 02–15」 | 仍成立;Multi-Raft 见 tikv-htap | 划界 |
| FDB strict serializable 分叉 | 16 否证 § strict serializable | 对照 |
| K8s 能否用 TiKV 替 etcd | 39 + 姊妹 §FAQ;默认仍 etcd | 已钉 |
三系列分工口令:
- 「Multi-Raft / Region / Percolator / TiFlash」→ tikv-htap/
- 「Sequencer / Resolver / OCC / Layer」→ foundationdb/
- 「Watch revision / Lease TTL / apiserver rv /
五轴排障」→ 本系列
- 「横向海报」→ distributed/39
姊妹终章 不必增写 etcd 运维章;本篇关闭「etcd 叶悬空」——读 TiKV/FDB 选型树时,etcd 分支已有可核对终章。
四、机制对照(不是吞吐排名)
| 维度 | etcd v3.5.33 | TiKV | FoundationDB |
|---|---|---|---|
| 扩展单位 | 单 Raft 组 | Multi-Raft Region | 角色 + shard |
| 协调原语 | Watch / Lease / Txn | KV + 分布式 SQL 栈 | KV + Layer |
| 容量边界 | quota 2–8 GB backend | PB 级 | 集群规模另论 |
| 一致读 | ReadIndex 线性读 | Percolator SI | Strict serializable |
| 存储引擎 | bbolt 单写者 | RocksDB LSM | Redwood 等 |
| 测试文化 | Raft + etcd 测试传统 | 集成/混沌 | 确定性模拟 |
本表不比较 QPS。需要数字时只引用各系统口径完整的官方报告,且不得冒充本站实测(WRITING_GUIDE.md §七)。
学术谱系(压缩):Raft(Ongaro & Ousterhout, USENIX ATC 2014)→ etcd 生产实现(Li et al., ;login: 2017)→ 本系列 v3.5.33 服务器路径。Multi-Raft 与 Percolator 分叉见 tikv-htap;Unbundled OCC 分叉见 foundationdb。协调 KV 与「事务 KV」边界仍是社区活跃讨论,不是「Soon 统一」。
五、开放问题
关闭条件必须是测量、Jepsen 类验证或正式文档/源码变更,不是路线图口号。
5.1 Watch 背压与 Compaction 的 SLO
问题:ErrCompacted 后全量
List 的成本如何写进 controller 与 apiserver
的 ADR?auto-compaction retention 与 watch
客户端断连时长如何定量 trade-off?
为何重要:轴 4 故障在大集群表现为
apiserver/etcd 双端风暴(第 13、15
篇)。
检验:声明集群对象规模与
retention;测量一次 forced resync 的 List 字节与
etcd/apiservers 延迟——本站无同构 peer-reviewed
数字,保持开放。
入口:etcd 官方 maintenance 文档;K8s
大规模 etcd 运维实践(B 级)。
5.2 Lease + fencing 与 K8s 语义
问题:Jepsen 证明 Lease
锁在部分故障序下不安全;K8s Node Lease + 控制器依赖 Lease
过期——应用层 fencing 是否足够?与 apiserver
全链路形式化 spec 仍缺。
为何重要:轴 5 与轴 1 联动(Leader 切换 +
mass expire)。
检验:混沌下 Node NotReady 与 Lease TTL
分布是否匹配 SLO。
现状:distributed/53
已钉 KV/Txn vs Lease 边界;K8s
全链路仍开放。
5.3 quota 触顶后的迁移路径
问题:events 分集群、降
churn、换存储之外,何时应评估 TiKV/FDB
而非继续调 etcd?Kine 等兼容层 Watch
语义差是否被系统性测试?
为何重要:否证条件 1–2 触发后的 ADR
缺模板。
检验:触顶前后五轴指标 + 业务是否真需要
Watch 历史。
现状:Kine 无与原生 etcd
同等的 Jepsen
覆盖(工程判断;保持开放)。
5.4 3.5 → 3.6/3.7 与 K8s 矩阵
问题:feature gate 替代 experimental
flag、v2 全移除后,发行版钉死的 etcd
版本与自建集群升级窗口如何对齐?
为何重要:第 14 篇
升级门;全 cluster 升 minor 后不可二进制回滚。
检验:升级前 snapshot + 官方
etcdutl check v2store + K8s release notes
三联。
现状:3.7 已发布(2026 SIG etcd
公告);各 K8s
发行版默认嵌入版本仍须逐家核对——开放。
给维护者:etcd patch 或 K8s minor 升级后,先更新 §5 的「现状」句,再决定是否改排除树问题顺序;live docs 能力未钉 tag 的不写入甜区。
六、边界关闭
| 题目 | 归属 | 关闭状态 |
|---|---|---|
| Raft 论文 / PreVote / ReadIndex 代码 | distributed/13、raft-etcd | 外链;本系列不重写 |
| Watch/MVCC 百科单篇 | distributed/50 | 外链;本系列补生产精度 |
| 三方 KV 海报 | distributed/39 | 外链;etcd 叶 本篇 + 01–15 关闭 |
| Multi-Raft / HTAP | tikv-htap/ | 外链;16 对照 |
| Unbundled / OCC | foundationdb/ | 外链;16 对照 |
| Jepsen 方法论 | distributed/53 | 外链;11/16 引用 |
| propose→apply→watch + 五轴 + K8s 耦合 + 运维 + 选型 | 本系列 01–16 | 已覆盖 |
| 未实测跨引擎 QPS/延迟榜 | — | 禁止 |
| Kine / SQL backend 兼容层全书 | 边界 | 未关闭(一句指针) |
| §5.1–5.4 开放项 | 上文 | 未关闭 |
给读完本系列的人三条收束(ADR 友好)
- 排除树进 ADR:写清卡在「quota / Watch /
五轴 /
事务模型」哪一叶;附否证条件(触顶、背压、编制、strict
serializable 需求、误把 TiKV 当 etcd 加速)。示例句:
「若 backend 连续触 alarm 或 Watch resync 占 apiserver P99,则 etcd 叶必须重跑排除树,禁止以『K8s 默认 etcd』阻止 events 分集群或迁移评估。」 - 若选了 etcd:第 15 篇五轴进 on-call;第
12 篇 compact/defrag 进变更窗;第 14 篇 snapshot
进升级门;第 13 篇 apiserver 分列进 504 runbook。
- 若没选 etcd:用第 16 篇 §四机制表做复盘;需要 Multi-Raft 回 tikv-htap/18;需要 strict serializable 回 foundationdb/18;禁止无口径吞吐截图重开争论。
终章立场:etcd
值得写成生产系列,是因为失败可命名——no leader、WAL
fsync、NOSPACE、ErrCompacted、Lease
雪崩。选型若离开这些名字,讨论退回「K8s 都用
etcd」。记住一个动作:先排除,再钉 v3.5.33(或发行版
patch),再写 quota SLO——排除自带否证,版本自带升级门,SLO
自带 Watch/Compaction 联合调参。
distributed/39、tikv-htap/18、foundationdb/18 留下的 etcd 协调叶 现已有可核对篇章。若读完仍只能复述「小数据用 etcd」,说明阅读停在海报;若能在故障里说出「这是 apply lag 不是 Raft 选举」或「这是 ErrCompacted 不是 quota」,机制文才算交货。
若读者时间只够两篇:读 第 1 篇 · 生产全景 建立五轴,再读本篇排除树;然后按主轴跳进 09/12/15 之一。完整通读的收益是「症状能落格」;跳读的风险是把 distributed/50 百科当成排障精度,或在 quota 触顶时继续加 etcd 节点。
给维护者:patch 级更新应改版本钉与 §五开放问题进展,而不是重写「先排除再选」的顺序。K8s 默认嵌入 etcd minor 变化时,更新 §5.4 与 第 14 篇 的交叉引用即可。
至此,etcd / 生产内核 系列在机制层闭合:从 Raft 嵌入到 WAL/MVCC/bbolt、读写 Watch Lease、K8s 耦合、运维升级、五轴排障,再到排除树。后续补丁级更新改版本钉与开放项,不重写五轴口令。
参考资料
规范 / 官方文档 / 源码(A)
核心论文
- Ongaro, D., & Ousterhout, J. (2014). In Search
of an Understandable Consensus Algorithm. USENIX
ATC.
- Li, X., et al. (2017). etcd: A Distributed Key-Value Store for Inspiring Reliable Distributed Systems. USENIX ;login:.
站内对照
- 系列目录
- distributed/39 · KV 对比
- distributed/50 · etcd 百科
- tikv-htap/18 · 选型
- foundationdb/18 · 选型
- distributed/53 · Jepsen
实验台账
- 本篇无跨方案 benchmark;选型依据为机制排除。开放问题关闭依赖测量或上游变更,不在此伪造时间线。
上一篇:排障五轴
下一篇:系列目录
读完这篇,下一步读什么
优先读同系列或同问题的下一篇,把单篇消费变成主题集群。
【etcd】生产全景:缺口、五轴坐标系与 16 篇路线
相对 distributed/50、39、13 钉清 etcd 生产内核缺口;定义 Raft/WAL/MVCC/Watch/Lease 五轴排障坐标系,给出 16 篇阅读路线与 K8s 控制面耦合指针。版本锚定 v3.5.33。
【etcd】单 Raft 组与服务器角色:Leader、Follower、Learner 与 request 路由
钉清 etcd v3.5.33 单 Raft 组拓扑、EtcdServer 与 go.etcd.io/raft/v3 边界、Leader/Follower/Learner 角色及 gRPC 写读路由;与 distributed/13 分工。
【etcd】WAL 与快照:预写日志、crash recovery 与 commit vs applied
拆解 etcd v3.5.33 的 WAL 段文件、Raft snapshot 触发与重启 recovery 顺序;钉清 committed index 与 applied index 分叉对排障与 K8s 控制面的含义。
【etcd】MVCC 数据模型:Revision、keyIndex 与 generation
拆解 etcd v3.5.33 的 Revision (main, sub) 全序、keyIndex/generation 生命周期与 treeIndex 分工;简要对照 v2 平面键空间,交代 MVCC 与 Watch/compaction 的语义基础。