2. etcd 核心原理回顾:Raft 协议、Leader 选举、读写路径、MVCC、事务与租约机制

在构建多集群 etcd 压测沙盘与 CAPI 指标告警体系之前,必须深入理解 etcd 的内部运行机制。etcd 作为云原生架构中的“协调中枢”,其核心原理直接决定了集群的可用性、一致性与性能瓶颈。本节将系统回顾 Raft 共识协议、Leader 选举、读写路径、MVCC、事务与租约机制,为后续的压测场景设计与告警分层奠定理论基础。

2.1 Raft 共识协议

Raft 是一种易于理解的分布式共识算法,etcd 使用它来保证集群中数据的一致性和高可用性。Raft 将共识问题分解为三个子问题:Leader 选举、日志复制和安全性。

核心要点: Raft 通过强 Leader 模型简化了复制流程。所有写操作必须经过 Leader,Leader 将日志条目复制到大多数 Follower 后,才视为提交成功。

Raft 集群中的每个节点有三种状态:

  • Leader:处理所有客户端请求,管理日志复制。
  • Follower:被动响应 Leader 和 Candidate 的请求。
  • Candidate:用于选举新 Leader 的过渡状态。

日志复制流程如下表所示:

步骤 操作 说明
1 客户端请求 写请求发送到 Leader
2 追加日志 Leader 将条目追加到本地日志
3 并行复制 Leader 向所有 Follower 发送 AppendEntries RPC
4 多数确认 Follower 写入本地日志后回复确认
5 提交应用 Leader 收到多数确认后提交日志,并应用到状态机
6 响应客户端 Leader 将结果返回给客户端
Raft 日志复制流程 Raft 日志复制流程 客户端 Leader Follower 1 Follower 2 写请求 AppendEntries AppendEntries 确认 确认 说明: 1. 写请求必须发送到 Leader。 2. Leader 将日志条目复制到所有 Follower,并等待多数确认。 3. 只有收到多数确认后,Leader 才提交日志并响应客户端。

2.2 Leader 选举

Leader 选举是 Raft 协议的核心机制之一,确保集群在 Leader 故障时能够快速恢复写入能力。选举过程基于随机超时时间和任期号。

选举流程如下:

  1. 超时触发:Follower 在选举超时内未收到 Leader 的心跳,转为 Candidate。
  2. 发起投票:Candidate 增加任期号,向其他节点发送 RequestVote RPC。
  3. 投票规则:每个节点在一个任期内只能投一票,且优先投票给日志更新的 Candidate。
  4. 赢得选举:Candidate 获得多数投票后成为 Leader,并立即发送心跳确立权威。
注意: 选举超时时间通常为 150ms ~ 300ms 的随机值,避免多个节点同时发起选举导致选票分裂。在压测场景中,频繁的 Leader 选举会显著增加写入延迟,是重要的告警指标。

2.3 读写路径

etcd 的读写路径设计直接影响性能与一致性。写路径必须经过 Raft 日志复制,而读路径则可以通过多种方式优化。

写路径

  • 序列化:Leader 将请求序列化为 Raft 日志条目。
  • 复制:日志条目并行复制到 Follower。
  • 持久化:节点将日志写入磁盘(WAL)。
  • 提交:多数节点确认后,Leader 提交日志。
  • 应用:日志应用到 MVCC 存储引擎。

读路径

etcd 提供三种读模式,适用于不同的一致性要求:

读模式 一致性 性能 适用场景
线性一致性读 强一致 低(需 Raft 确认) 关键配置读取
串行化读 最终一致 高(本地读取) 监控数据、非关键状态
允许陈旧读 弱一致 最高 缓存、日志
压测建议: 在沙盘压测中,应分别测试线性一致性读和串行化读的性能差异,观察 Raft 确认带来的延迟开销。线性一致性读的延迟通常比串行化读高 2-5 倍。

2.4 MVCC(多版本并发控制)

etcd 使用 MVCC 机制管理键值对的历史版本,支持事务和快照操作。每个键的每次修改都会生成一个新的版本号(revision),旧版本不会被立即删除,而是保留一段时间。

MVCC 的核心数据结构:

  • treeIndex:内存中的 B-tree,维护键到最新版本的映射。
  • boltDB:底层持久化存储,按版本号存储键值对。
  • revision:全局递增的版本号,由主版本号和子版本号组成。

MVCC 的压缩机制(Compaction)用于清理历史版本,避免存储膨胀:

压缩类型 操作 影响
历史版本压缩 删除指定 revision 之前的所有版本 释放存储空间,但无法读取历史数据
碎片整理 重新整理 boltDB 文件,回收空闲页 减少磁盘占用,提升读性能
关键指标: 在压测中,需要监控 etcd_db_total_size_in_bytes 和 etcd_compaction_revision,确保压缩及时执行,避免磁盘空间耗尽。

2.5 事务与租约机制

事务

etcd 支持基于 if-then-else 模型的事务操作,允许在单个原子操作中执行多个条件判断和键值修改。事务的原子性由 Raft 协议保证。

事务结构示例:

// 事务:如果 key1 的值为 "v1",则更新 key2,否则删除 key3
Txn:
  compare:
    - target: "value"
      key: "/key1"
      result: "EQUAL"
      value: "v1"
  success:
    - request_put:
        key: "/key2"
        value: "v2"
  failure:
    - request_delete_range:
        key: "/key3"

事务的典型应用场景:

  • 分布式锁:通过比较创建 revision 实现锁的获取与释放。
  • 配置更新:确保配置的原子性更新,避免部分写入。
  • 服务注册:结合租约实现服务的健康检查与自动摘除。

租约机制

租约(Lease)是 etcd 中的一种时间租约机制,用于管理键值对的生存周期。租约与键绑定,租约过期时,所有关联的键会被自动删除。

租约的核心属性:

属性 说明 默认值
TTL 租约的生存时间(秒) 用户指定
ID 租约的唯一标识 自动生成
KeepAlive 客户端定期续约,防止租约过期 需要主动调用
压测场景: 在沙盘中,可以通过大量创建短 TTL 租约并模拟 KeepAlive 超时,测试 etcd 的租约过期处理能力和事件通知延迟。租约风暴是常见的压测场景之一。
事务与租约交互流程 事务与租约交互流程 客户端 etcd Server 租约管理器 事务请求 绑定租约 租约过期 删除键通知 说明: 1. 客户端通过事务创建键并绑定租约。 2. 租约管理器监控租约 TTL,到期后通知 etcd Server 删除关联键。 3. 客户端可通过 KeepAlive 续约,避免键被自动删除。

2.6 核心原理总结

etcd 的核心原理构成了分布式协调服务的基础,也是压测沙盘设计的关键依据。下表总结了各机制对压测的影响:

机制 压测关注点 相关告警指标
Raft 协议 日志复制延迟、多数派故障 etcd_raft_proposal_failed_total, etcd_server_leader_changes_seen_total
Leader 选举 选举耗时、频繁切换 etcd_server_leader_election_duration_seconds
读写路径 读写延迟、吞吐量 etcd_disk_wal_fsync_duration_seconds, etcd_network_client_traffic_in_bytes
MVCC 版本堆积、压缩延迟 etcd_db_total_size_in_bytes, etcd_compaction_revision
事务与租约 事务冲突、租约风暴 etcd_txn_total, etcd_lease_expired_total
下一步: 在掌握 etcd 核心原理后,我们将进入第 3 章,设计多集群 etcd 压测沙盘的架构与部署方案,将理论转化为可观测的压测环境。