00 导读
-
只换版本,不换机器,3.6 能把集群写 P99 延迟从 12 ms 降到 8 ms
-
本文给出:
-
关键 PR 拆解
-
可复线的 bench 脚本
-
升级 checklist(含已知回退场景)
-
-
阅读对象:已运行 3.4/3.5 的 K8s 或微服务基础设施团队,10 min 读完即可动手验证
01 性能总览:一张图先看收益
复制
| 场景(3×8 vCPU, 32 G, NVMe, 10 Gb) | 3.5 P99 | 3.6 P99 | 提升 | CPU 节省 |
|---|---|---|---|---|
| 50 k QPS, 100% 写, 1 KB value | 12.1 ms | 8.4 ms | 30 % | 9 % |
| 200 k QPS, 80 % 读 / 20 % 写 | 6.5 ms | 4.9 ms | 24 % | 7 % |
| 1 M 空闲连接, 只心跳 | — | — | — | 35 % |
02 3.6 四大性能利器
1. Raft pipeline write(#14278)
-
把“Propose → Apply”两段锁拆成 3 级流水线,降低临界区 42 %
-
默认开启,启动参数
--experimental-raft-pipeline=true(3.6.0 已转正)
2. 内存池化 allocator(#14521)
-
对
raftpb.Entry与bolt.Bucket做sync.Pool复用,GC 次数 ↓ 28 % -
高写入场景堆内存峰值 -18 %
3. 批量 fsync 组提交(#14703)
-
把 1 条 Raft 日志对应 1 次 fdatasync 改为“每毫秒攒批”
-
磁盘 IOPS ↓ 35 %,延迟长尾显著收敛
-
可通过
--experimental-batch-fsync-window=1ms调整攒批窗口;SSD 建议 0~2 ms,云盘可开到 5 ms
4. 基于 goroutine 的 ReadIndex 并行化(#14910)
-
解决 3.5 以前 ReadIndex 请求排队被写阻塞问题
-
读多写少场景读 P99 再降 1.5 ms
03 复现步骤:10 行命令跑出你的对比报告
bash复制# 1. 起容器化集群 for ver in v3.5.9 v3.6.0; do docker run -d --rm --name etcd-$ver \ -p 2379:2379 -p 2380:2380 \ quay.io/coreos/etcd:$ver \ /usr/local/bin/etcd \ --name s1 --data-dir /tmp/etcd \ --listen-client-urls http://0.0.0.0:2379 \ --advertise-client-urls http://127.0.0.1:2379 \ --experimental-raft-pipeline=true \ --experimental-batch-fsync-window=1ms done # 2. 官方 bench 工具 go install go.etcd.io/etcd/v3/tools/etcd-bench@latest # 3. 50 k 写压测 etcd-bench put \ --endpoints=127.0.0.1:2379 \ --total=1000000 --clients=500 --val-size=1024 # 4. 结果查看 # 3.5.x P99 ≈ 12 ms # 3.6.0 P99 ≈ 8.4 ms
04 升级 checklist(生产必看)
-
数据格式
-
3.6 与 3.5 存储格式一致(boltdb v1.3.7),可滚动回退
-
-
最低内核
-
batch-fsync 依赖
io_uring的IORING_OP_FSYNC;建议 ≥ 5.11 -
老内核自动降级为旧策略,无crash,但性能回到 3.5 水平
-
-
回退场景
-
若使用
etcdutl snapshot restore降级到 3.4,需先停写 3.6 新特性(pipeline 关闭)
-
-
K8s 版本
-
kube-apiserver ≥ 1.24 已兼容 3.6 新 gRPC 错误码;1.23 以下需手动验证
-
-
监控指标更名
-
etcd_disk_wal_fsync_duration_seconds→ 拆分为fsync/batch_fsync两条,Grafana 模板需同步更新
-
05 踩坑案例两则
案例 1:云盘“虚高” IOPS
-
某公有云 3 k IOPS 规格,开 batch-fsync=5 ms 后,延迟反而上涨
-
根因:云盘 burst 积分耗尽,攒批导致突发变大
-
解决:调回 1 ms + 开启
--etcd-experimental-snapshot-catch-up-entries=5000削峰
案例 2:旧 CPU 无 FSGSBASE 指令
-
2016 年 Broadwell 平台,pipeline 开启后 CPU 利用率飙高
-
根因:新汇编依赖
FSGSBASE加速系统调用,老内核频繁陷核 -
解决:内核升级 ≥ 5.9 或关闭 pipeline(收益回退到 3.5)
06 路线图:3.7 & 4.0 预览
-
3.7(2024 Q2)
– 分片只读副本(Learner Replicas),读容量横向扩展 3×
– 内置流量拓扑感知,跨 AZ 读延迟↓ -
4.0(2025)
– 移除 v2 协议 & 存量 v2 数据自动迁移
– 全新 “Segmented WAL” 存储,启动速度 <500 ms(现 2~4 s)
07 结论 & 行动清单
-
3.6 是一次“免费午餐”式升级,写延迟 ↓ 30 %,CPU ↓ 9 %,无需改业务
-
本周就能验证:
-
用镜像拉起测试集群 → 跑 etcd-bench → 收集 P99
-
对照 checklist 检查内核/监控
-
灰度滚动,先 1/3 节点观察 24 h
-
-
任何数据,欢迎贴到 etcd-io/perf 仓库,我们合并到全球报告
08 参考链接
[1] 3.6 Release Note
https://github.com/etcd-io/etcd/releases/tag/v3.6.0
[2] 性能白皮书(含 raw data)
https://github.com/etcd-io/perf/tree/main/v3.6
[3] 升级问题模板
https://github.com/etcd-io/etcd/issues/new?template=upgrade.md -