2. etcd 基础架构回顾:Raft 共识算法原理、集群角色与存储引擎

在深入灾备与压测之前,必须重新审视 etcd 的底层架构。etcd 本质上是一个强一致性的分布式键值存储系统,其核心由三层构成:共识层(Raft)、集群角色层和存储引擎层(BoltDB)。理解这三层的协作关系,是制定灾备策略和解读压测指标的前提。

2.1 Raft 共识算法原理

Raft 是一种易于理解的分布式共识算法,它通过领导者选举和日志复制两个核心机制,确保集群中所有节点数据最终一致。etcd 使用 Raft 来保证即使部分节点故障,集群仍能对外提供一致的服务。

核心要点: Raft 将共识问题分解为三个子问题:领导者选举(Leader Election)、日志复制(Log Replication)和安全性(Safety)。

2.1.1 领导者选举与任期

Raft 集群中的每个节点都处于三种状态之一:Follower、Candidate 或 Leader。选举过程通过任期(Term)来划分时间片,每个任期最多只有一个 Leader。

  • 选举触发: Follower 在选举超时时间内未收到 Leader 的心跳,则转换为 Candidate 并发起选举。
  • 投票机制: Candidate 获得超过半数(N/2+1)节点的投票,即可成为 Leader。
  • 心跳维持: Leader 定期向所有 Follower 发送心跳(AppendEntries RPC),重置选举超时计时器。

2.1.2 日志复制与提交

所有写操作必须经过 Leader。Leader 将客户端请求封装为日志条目(Log Entry),并复制到大多数 Follower 节点后,才将日志标记为已提交(Committed)并应用到状态机。

  1. 客户端向 Leader 发送写请求。
  2. Leader 将请求追加到本地日志,并并行向 Follower 发送 AppendEntries RPC。
  3. 当 Leader 收到大多数节点的成功响应后,日志条目进入已提交状态。
  4. Leader 将结果返回给客户端,并通知 Follower 应用该日志到状态机。
灾备启示: 日志复制需要多数派确认。如果集群因故障丢失多数节点(如 3 节点集群只剩 1 个节点),将无法提交新日志,集群进入只读或不可用状态。这是灾备设计的关键阈值。
Raft 日志复制流程 Leader Follower 1 Follower 2 ① 客户端写请求 ② AppendEntries RPC ③ 成功响应(多数派) ④ 日志提交,返回客户端 关键:只有日志被复制到多数节点(此处为 2/3)后,才视为已提交

2.2 etcd 集群角色:Leader / Follower

etcd 集群通常由奇数个节点组成(如 3、5、7),每个节点在 Raft 协议下扮演特定角色。角色并非固定不变,故障时会动态转换。

角色 职责 状态特征 灾备关注点
Leader 处理所有客户端写请求;管理日志复制;发送心跳 唯一;定期发送心跳;拥有最新日志 Leader 故障触发重新选举,期间不可写
Follower 处理读请求(可配置);转发写请求给 Leader;参与投票 被动;接收心跳;同步 Leader 日志 Follower 故障不影响写入,但降低读可用性
Candidate 选举过渡角色;发起投票请求 短暂存在;选举超时后触发 选举风暴可能导致集群短暂不可用
压测陷阱: 在高并发写入压测时,如果 Leader 节点负载过高导致心跳超时,可能触发不必要的重新选举。压测前应监控 Leader 的 CPU 和网络延迟,确保选举超时参数(--election-timeout)配置合理。

2.3 数据模型与存储引擎:BoltDB

etcd 的数据最终持久化在底层的 BoltDB 中。BoltDB 是一个基于 B+ 树的嵌入式键值存储引擎,支持事务和 ACID 特性。理解 BoltDB 的结构有助于分析 etcd 的读写性能瓶颈和磁盘空间占用。

2.3.1 数据模型层次

etcd 的数据模型分为三层:

  • Key-Value 层: 用户可见的逻辑键值对,支持前缀查询和目录结构。
  • MVCC 层: 多版本并发控制,每个修改生成一个新的版本号(revision),支持历史版本查询和 Watch 机制。
  • BoltDB 层: 物理存储层,将 MVCC 数据以 B+ 树结构持久化到磁盘文件(通常是 member/snap/db)。

2.3.2 BoltDB 存储结构

BoltDB 内部使用 Bucket 来组织数据。etcd 主要使用两个核心 Bucket:

Bucket 名称 存储内容 Key 格式 Value 格式
key 用户键值对的主数据 revision(主键 + 子ID) 用户 Value + 元数据
meta 集群元数据(如当前 revision、集群 ID) 固定名称 序列化结构体
性能启示: BoltDB 的 B+ 树特性决定了顺序写入性能远优于随机写入。etcd 的 MVCC 机制天然将写入转化为顺序追加(新 revision 递增),这是 etcd 写入性能较高的底层原因。压测时应避免大量跨 revision 范围的随机读取,这会导致 B+ 树频繁分裂。
etcd 数据模型与 BoltDB 存储架构 用户 Key-Value 层 /foo/bar = "value1" (逻辑视图,支持前缀查询) MVCC 多版本控制层 每个修改生成唯一 revision (全局递增),支持历史版本与 Watch BoltDB 存储引擎层 (B+ Tree) Bucket: "key" Key: revision → Value: 用户数据 Bucket: "meta" Key: 固定名称 → Value: 集群元数据 BoltDB 文件位置:/var/lib/etcd/member/snap/db (单文件存储所有数据)

2.4 架构总结:三者的协作关系

etcd 的一次完整写入流程,串联了上述三个核心组件:

  1. 客户端 → Leader: 写请求通过 gRPC 发送到集群 Leader。
  2. Raft 层: Leader 将请求封装为日志条目,通过 Raft 协议复制到多数 Follower。
  3. 状态机应用: 日志提交后,Leader 将数据应用到 MVCC 状态机,生成新的 revision。
  4. BoltDB 持久化: MVCC 将数据以 revision 为 Key 写入 BoltDB 的 "key" Bucket,并更新 "meta" Bucket。
  5. 返回客户端: Leader 向客户端返回写入成功响应。