首页
/ etcd 3.1 系列发行说明深度解读:read-index 线性化读加速、选举 tick 控制与可观测性指标演进

etcd 3.1 系列发行说明深度解读:read-index 线性化读加速、选举 tick 控制与可观测性指标演进

2026-09-05 12:55:31作者:何举烈Damon

etcd 3.1 系列(v3.1.0 至 v3.1.21,2017-01 至 2019 年)是从 v3.0 迈向生产成熟度的关键版本线:它在主干引入了 Raft read-index 加速线性化读、稳定化 v3 认证 API,并在后续补丁版本中围绕选举 tick 控制、快照/watcher 稳定性与 Prometheus 指标体系做了一连串精细化修复与增强。本文基于 CHANGELOG-3.1.md 逐版本梳理这一完整演进脉络,并结合当前仓库源码印证 read-index 时代的选举快进机制、快照一致性校验与客户端租约保活等关键实现,帮助读者理解这些变更背后的设计动机与实际影响,从而为版本选择、故障排查与升级决策提供可靠依据。

版本全景:3.1 系列覆盖的发布谱系

CHANGELOG 收录的 3.1.x 版本按时间从旧到新共 20 个条目,编译所用 Go 工具链也从 Go 1.7.4 逐步演进到 Go 1.8.7:

版本 发布日期 核心主题 编译 Go 版本
v3.1.0 2017-01-20 read-index 线性化读、认证 API 稳定、新 flag 与 gRPC Proxy Go 1.7.4
v3.1.1 2017-02-17 工具链升级 Go 1.7.5
v3.1.2 2017-02-24 gateway 多端点修复、默认 IPv4 host Go 1.7.5
v3.1.3 2017-03-10 gateway/gRPC Proxy 的 sd_notify 修复 Go 1.7.5
v3.1.4 2017-03-22 工具链升级 Go 1.7.5
v3.1.5 2017-03-27 raft 内存泄漏修复、Windows 路径修复 Go 1.7.5
v3.1.6 2017-04-19 Auth API 响应头、Status API 去鉴权 Go 1.7.5
v3.1.7 2017-04-28 工具链升级 Go 1.7.5
v3.1.8 2017-05-19 工具链升级 Go 1.7.5
v3.1.9 2017-06-09 允许超过 512MB 的 v2 快照 Go 1.7.6
v3.1.10 2017-07-14 Docker 镜像增加 minor 版本 tag Go 1.8.3
v3.1.11 2017-11-28 回移 mvcc restore 事件发送与 bbolt 修复 Go 1.8.5
v3.1.12 2018-03-08 unsynced watcher 恢复修复 Go 1.8.7
v3.1.13 2018-03-29 重启时选举超时调整 Go 1.8.7
v3.1.14 2018-04-24 新增 --initial-election-tick-advance flag、etcd_server_is_leader 指标 Go 1.8.7
v3.1.15 2018-05-09 --max-snapshots 清理旧 *.snap.db Go 1.8.7
v3.1.16 2018-05-31 修复 mvcc 快照恢复导致的 panic Go 1.8.7
v3.1.17 2018-06-06 v3 快照恢复(先落盘再加载) Go 1.8.7
v3.1.18 2018-06-15 新增 etcd_server_version 指标 Go 1.8.7
v3.1.19 2018-07-24 存储尺寸/配额指标体系 Go 1.8.7
v3.1.20 2018-10-10 快照一致性校验、gRPC 调试拦截器、快照收发指标 Go 1.8.7
v3.1.21 2019(TBD) etcdctl endpoint health 输出、db 压缩时长指标修复

更早的 v3.0 历史见 CHANGELOG-3.0.md。需要说明的是:3.1 系列发布于 2017–2019 年,文中对当前仓库源码的引用仅用于印证这些特性"现在长什么样",部分行为在后续版本中已演进(如 --max-snapshots 被移除),引用时需注意适用前提。

v3.1.0 奠基特性:read-index 线性化读与稳定认证

v3.1.0 是该系列最重要的版本,两大标志性改进如下:

1. 更快的线性化读(Raft read-index)

v3.1.0 实现了 Raft read-index 协议:只读请求不再需要走完整的 propose-commit 流程,leader 只需确认自己仍是 leader(通过任期编号与多数派回显的读索引机制)即可直接服务读请求。这是 etcd 读性能量级提升的基础,也是后续 v3.1.x 中"read index wait timeout 告警日志"(PR #10026)、etcd_server_slow_read_indexes_totaletcd_server_read_indexes_failed_total 等观测项存在的原因——它们都在监控 read-index 机制本身的健康度。

2. v3 认证 API 稳定化

v3 authentication API 自 v3.1.0 起标记为稳定(stable)。配套的安全细节变更包括:

  • 未提供自定义 CA 时,SRV 记录(如 infra1.example.com)必须匹配 discovery 域名(example.com);
  • TLSConfig.ServerName 在用户证书场景下被忽略(为向后兼容保留,计划弃用);
  • 例如 etcd --discovery-srv=example.com 只会在所提供证书的 SAN 字段包含根域 example.com 时才认证 peer/client。

3. 破坏性变更与依赖升级

  • 弃用了 4 个自研 gRPC 指标,改用 go-grpc-prometheus 生态方案:etcd_grpc_requests_totaletcd_grpc_requests_failed_totaletcd_grpc_active_streamsetcd_grpc_unary_requests_duration_seconds
  • 依赖 github.com/ugorji/go/codec 升级并重新生成 v2 client 代码。

4. 服务端行为与 flag 变化

  • 新增 --log-output--metrics flag;--strict-reconfig-check 改为默认开启;
  • advertise URL 缺省时使用默认路由 IP;
  • 集群拒绝会丢失 quorum 的 member 移除请求;
  • discovery 等待重试引入上限;
  • 通过域名绑定 listener 会告警(计划弃用);
  • leader 主动下线时自动发生 leadership transfer。

5. 自动压缩(auto-compaction)语义

v3.0 与 v3.1 中 --auto-compaction-retention=10 的运行机制在 CHANGELOG 中被完整描述,值得保留为运维参考:

  • Compactor 只支持周期性压缩(periodic compaction);
  • 每 5 分钟记录一次最新 revision,直到到达第一个压缩周期(如 10 小时);
  • 为保留上一个压缩周期的历史,它使用压缩周期开始前最后一次采集到的 revision(例如 --auto-compaction-retention=10 时,用"10 小时前获取到的 revision 100"作为 compact revision);
  • 压缩成功或目标 revision 已被压缩后,重置周期计时器并重新开始采集 revision 记录;
  • 压缩失败则 5 分钟后重试。

6. client v3 与 etcdctl v3 新能力

client v3 侧:新增 SetEndpoints(运行时更新端点)、Sync(自动更新端点)、Lease.TimeToLive API;用全局 logger 替换 Config.Logger 字段;Get API 响应默认按 key 升序排序。

etcdctl v3 侧:新增 lease timetolive 命令、get 命令的 --print-value-only flag、make-mirror 的 --dest-prefix flag,get 响应同样默认升序。

7. 实验性 gRPC Proxy

v3.1.0 引入了实验性的 gRPC proxy 功能(对应当前仓库 server/proxy/grpcproxy/ 目录),用于 v2 客户端平滑迁移到 v3。v3.1.2/v3.1.3 中多次修复了 gateway 多端点支持与 gatewaygrpc-proxy 的 sd_notify 行为。

选举 tick 快进机制:从问题到可控 flag 的演进

3.1 系列中关于"重启/重加入时触发破坏性选举"的修复经历了三个版本,构成一个完整的调优故事:

v3.1.13(2018-03-29):服务端启动时选举超时的调整。此前 etcd 在服务启动时快进 election ticks,只留 1 个 tick 的选举窗口,以加速跨数据中心等大选超时场景下的启动阶段;但如果最后一个 tick 在 leader 联系上重启节点之前耗尽,就会触发破坏性选举,影响集群可用性。修复后,etcd 重启时会调整 election ticks 使剩余 tick 大于 1,给 leader 留出更多时间发送心跳。

v3.1.14(2018-04-24):新增 --initial-election-tick-advance flag,把该行为变成可配置项:

  • 默认 --initial-election-tick-advance=true,本地 member 快进 election ticks 以加速"初始" leader 选举;
  • 典型收益:跨数据中心部署可能要求 10 秒的 election timeout,快进后节点无需等待满 10 秒(例如快进到 8 秒,只剩 2 秒即触发选举);
  • 成立前提:集群无活跃 leader(快进加速选举),或集群已有 leader 且重加入 follower 大概率在选举超时前收到心跳;
  • 风险:若 leader 到重加入 follower 的网络拥塞、剩余 tick 内收不到心跳,就会发生破坏性选举;
  • 因此可用 --initial-election-tick-advance=false 关闭,代价是跨数据中心初始 bootstrap 变慢;
  • 单节点集群无论该 flag 如何都执行快进。

当前仓库源码印证了这一机制的最终形态:

  • flag 定义与默认值(true)见 embed/config.goembed/config.go,配置字段及注释见 config/config.go
  • 启动时的快进逻辑见 etcdserver/server.go:单节点(clusterN == 1)无条件执行 advanceTicks(ElectionTicks-1);多节点场景下,若 InitialElectionTickAdvancefalse 则直接跳过(打印 "skipping initial election tick advance"),否则先等待 peer 连接报告(间隔 50ms,上限 rafthttp.ConnReadTimeout 约 5 秒),确认有活跃 peer 后才继续快进——即 CHANGELOG 中"无活跃 peer 时快进无意义"的假设在代码中得到了落实。

快照与 watcher 稳定性修复链

3.1.x 中四个版本围绕"快照 + watch 恢复"修复了若干会导致丢事件甚至 panic 的问题,是理解 etcd 崩溃恢复语义的好材料:

v3.1.15 —— 尊重 --max-snapshots 清理旧快照:此前 etcd 未按 --max-snapshots 清理磁盘上的旧 *.snap.db 文件,修复后保留至多 --max-snapshots 个文件。值得注意的是,从当前仓库源码结构看,该 flag 在后续版本已被移除,改为固定常量 maxSnapDBFiles = 5(见 etcdserver/server.go 的注释:"It's no longer configurable now that --max-snapshots is removed")。

v3.1.12 —— 修复 "unsynced" watcher 恢复:"unsynced" watcher 指需要在与过去事件重新同步的慢 watcher(请求了较旧 revision 的 watcher)。典型场景:某节点带着一个指向未来 revision 的 watcher 发生网络分区,分区解除后 leader 向其发送快照;应用快照时,watch storage 会把当前 synced watchers 移入 unsynced 组(分区期间可能已过期)并重置组以重启 watcher 例程。旧代码在 synced → unsynced 迁移时未正确填充底层 watcher 组,导致客户端可能丢失事件。

v3.1.16 —— 修复 mvcc 恢复 panic:假设 watcher 请求了未来 revision X 并发往节点 A,随后 A 网络分区;分区期间集群继续推进,分区解除后 leader 向 A 发快照。旧逻辑下,若快照的最新 revision 仍低于 watch revision X,etcd server 会在快照恢复时直接 panic,该问题在 v3.1.16 修复。

v3.1.17 —— v3 快照先落盘再加载:follower 收到 leader 的快照并持久化为 [SNAPSHOT-INDEX].snap.db 文件。修复前,服务器不保证快照文件先写入磁盘再被加载;一旦 WAL 中出现比快照 index 更新却基于过期快照的条目,会发生 index 不匹配并触发 server panic。修复后,服务器确保收到快照先持久化到磁盘、然后再加载。

v3.1.20 —— 快照状态一致性校验snapshot status 增加一致性检查,快照文件校验失败时返回 "snapshot file integrity check failed..." 错误。其底层机制在当前仓库中依然可见:服务端在发送快照流时同步计算 SHA-256 摘要,并在数据流末尾单独发送该摘要供恢复端校验,见 v3rpc/maintenance.go 中 "record SHA digest of snapshot data / used for integrity checks during snapshot restore operation" 的注释。

可观测性:3.1 系列补齐的 Prometheus 指标体系

CHANGELOG 每个版本的 "Metrics, Monitoring" 小节均提示:所有 etcd_debugging_* 前缀指标为实验性,可能随时变化。3.1 系列逐步补齐了如下生产级指标(按引入版本):

版本 新增指标 用途说明
v3.1.13 etcd_network_peer_sent_failures_total(补计数) peer 消息发送失败
v3.1.14 etcd_server_is_leader 判断节点是否为 leader
v3.1.18 etcd_server_version 替代 Kubernetes 侧的 etcd-version-monitor
v3.1.19 etcd_server_go_version 运行二进制所用 Go 版本
v3.1.19 etcd_server_slow_read_indexes_total read-index 慢请求
v3.1.19 etcd_server_quota_backend_bytes 当前配额大小
v3.1.19 etcd_mvcc_db_total_size_in_bytesetcd_mvcc_db_total_size_in_use_in_bytes DB 物理分配尺寸 / 实际使用尺寸
v3.1.20 etcd_server_idetcd_server_health_successetcd_server_health_failures 节点身份与健康检查结果
v3.1.20 etcd_server_read_indexes_failed_total read-index 失败
v3.1.20 etcd_snap_db_fsync_duration_seconds_countetcd_snap_db_save_total_duration_seconds_bucket 快照 fsync / 保存耗时
v3.1.20 etcd_network_snapshot_send_success/failures/total_duration_secondsetcd_network_snapshot_receive_success/failures/total_duration_seconds 快照发送/接收成功失败与耗时

其中三项指标的组合用法在 CHANGELOG 中有明确示范,值得原样保留为运维公式:

etcd_server_quota_backend_bytes 2.147483648e+09     # 当前配额大小(2 GB)
etcd_mvcc_db_total_size_in_bytes 20480              # 当前物理分配 DB 尺寸(20 KB)
etcd_mvcc_db_total_size_in_use_in_bytes 16384       # 完成 defrag 后的 DB 尺寸

可回收空间 = etcd_mvcc_db_total_size_in_bytes - etcd_mvcc_db_total_size_in_use_in_bytes

v3.1.20 还做了两项观测能力增强:

  • etcd_network_peer_round_trip_time_seconds 从"只采样快照消息的 TCP 连接"改进为追踪 leader 心跳,样本更有代表性;
  • 启动时打印所有已注册的 gRPC 指标;并新增 gRPC 调试拦截器,启用 etcd --debug 可查看逐请求的调试信息。

v3.1.21 则修复了 db_compaction_total_duration_milliseconds 指标恒测得 0 的 bug。

etcdctl 与 client v3:保活、锁与健康检查

endpoint health 输出修复(v3.1.21):此前 etcdctl endpoint health --write-out json 不可用(对应 issue #9532),v3.1.21 修复后统一了输出格式——无论何种错误类型,不可达端点的输出统一为 "<endpoint> is unhealthy: failed to commit proposal: <error message>"。当前仓库中集群不健康时 etcdctl 以退出码报错的分支见 ep_command.gounhealthy cluster)。此外该版本还剔除了 discovery 时 DNS SRV 记录中的不安全端点。

租约 keepalive 节奏修复(v3.1.19):若 clientv3.Lease.KeepAlive 返回的 <-chan *clientv3LeaseKeepAliveResponse 从未被消费或队列已满,客户端曾以每 500ms 一次(而非预期的 TTL/3 间隔)发送 keepalive 请求,造成无谓的服务器压力;v3.1.19 修复了响应队列满时的 keepalive 间隔更新逻辑。当前仓库的 lease.go 仍保留了这一语义:KeepAlive 会尽最大努力永久续租,底层保活通道关闭或不可恢复错误时会返回 ErrKeepAliveHalted,提示"自动续租已损坏但 KeepAliveOnce 仍可用"。

并发包释放锁修复(v3.1.20)clientv3/concurrency 包在取消(cancelled)场景下会错误地释放锁 key,v3.1.20 修正了"取消时释放锁 key"的逻辑。

v3.1.11 的回移项:该版本回移了 "mvcc: sending events after restore"(issue #8411)与 coreos/bbolt v1.3.1-coreos.5(issue #8009),说明 3.1 分支在生命周期后期仍在接收主干修复,使用 3.1.x 生产集群时应尽量跟进高编号补丁版本。

升级与适用性提示

  • CHANGELOG 在几乎每个版本都反复强调:升级前务必先读版本说明与 v3.1 upgrade guide(官方文档站),v3.1.0 相对 v3.0.0 存在破坏性变更(主要是 gRPC 指标弃用),v2→v3 用户应重点核对认证与 TLS 相关行为;
  • 3.1.x 各版本编译 Go 版本为 Go 1.7.4~1.8.7,属于历史工具链信息;若当前仓库(主干分支)构建,应以仓库根目录 go.mod 声明的 Go 版本为准,二者不可混用;
  • 本文引用的源码路径均基于当前仓库主干,用于印证 3.1 系列引入机制的现状;对已演进的特性(如 --max-snapshots 移除、read-index 相关指标继续扩展),请以对应版本的 release tag 代码为准。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384