2. etcd 架构解析:Raft 共识算法原理、存储引擎与 WAL/快照机制
要准确评估 etcd 多集群的容量水位,必须先深入理解 etcd 的内部架构。本章将拆解 etcd 的三大核心支柱:Raft 共识算法(保证数据一致性)、BoltDB 存储引擎(持久化键值数据)、以及 WAL 日志与快照机制(保障数据安全与恢复)。这三者共同决定了 etcd 的性能边界、存储开销与故障恢复能力,是容量水位评估的理论基础。
2.1 Raft 共识算法:分布式一致性的基石
etcd 使用 Raft 算法在多个节点间复制日志,确保即使部分节点故障,集群仍能对外提供强一致性的读写服务。Raft 将节点划分为三种角色:Leader、Follower 和 Candidate。
2.1.1 角色与任期
- Leader: 处理客户端请求,管理日志复制,定期发送心跳(Heartbeat)给 Follower。
- Follower: 被动响应 Leader 和 Candidate 的请求。如果收不到有效心跳,会超时并转为 Candidate。
- Candidate: 发起选举,请求其他节点投票。获得多数票后成为 Leader。
Raft 将时间划分为一个个 任期(Term),每个任期最多只有一个 Leader。任期号单调递增,用于防止脑裂和过时消息干扰。
2.1.2 日志复制流程
- 客户端将写请求发送给 Leader。
- Leader 将请求追加到自己的 WAL 日志中,形成一条未提交的日志条目。
- Leader 并行向所有 Follower 发送
AppendEntriesRPC,包含该日志条目。 - Follower 收到后,先写入本地 WAL,然后返回成功响应。
- Leader 收到多数(Quorum)Follower 的成功响应后,将该日志条目标记为已提交(Committed),并应用到状态机(BoltDB)。
- Leader 通知 Follower 该条目已提交,Follower 随后也应用到本地状态机。
2.2 etcd 的存储引擎:BoltDB
etcd 使用 BoltDB 作为底层持久化键值存储。BoltDB 是一个基于 B+ 树 的嵌入式数据库,支持事务(ACID)和快照隔离级别。etcd 将 Raft 日志最终应用到 BoltDB 中,形成最新的键值数据。
| 特性 | 说明 | 对容量水位的影响 |
|---|---|---|
| B+ 树结构 | 所有键值对按字典序存储在 B+ 树中,支持高效的范围查询和顺序遍历。 | 数据量增大时,B+ 树层级加深,读写放大效应明显,内存和磁盘占用增加。 |
| 事务支持 | etcd 的每次写操作(Put、Delete、Txn)都是一个 BoltDB 读写事务。 | 长时间运行的事务会阻塞其他读写,影响并发性能,需监控事务持续时间。 |
| 只读事务(快照) | etcd 的读请求默认使用只读事务,获取一个一致性的数据快照,不阻塞写。 | 大量并发读请求会创建大量快照对象,增加内存压力。 |
| 空闲列表(Freelist) | BoltDB 维护一个空闲页列表,用于回收已删除数据占用的磁盘空间。 | 频繁的删除和更新操作会导致空闲页碎片化,数据库文件大小不会自动缩小,需定期碎片整理(defrag)。 |
db_total_size 和 db_open_read_transactions 是容量水位评估的核心指标。前者反映磁盘占用,后者反映读压力。当 db_open_read_transactions 持续高位时,需排查是否存在慢读事务。
2.3 WAL 日志与快照机制
WAL(Write-Ahead Log)和快照是 etcd 数据持久化和恢复的两大支柱。WAL 记录所有操作,快照则压缩历史日志,防止日志无限增长。
2.3.1 WAL 日志
所有写入操作(包括 Raft 日志条目和集群元数据变更)在应用到状态机之前,必须先写入 WAL 文件。WAL 文件按段(Segment)组织,每个段文件大小默认为 64MB。WAL 写入采用 顺序追加 模式,性能远高于随机写。
- 写入流程: 每次写请求先序列化为 WAL 记录,追加到当前 WAL 段文件,并调用
fsync刷盘。刷盘成功后,才返回客户端成功。 - 文件轮转: 当前 WAL 段文件写满后,创建新的段文件。etcd 会保留一定数量的历史 WAL 文件,用于数据恢复。
- 恢复过程: 节点重启时,从最早的 WAL 文件开始,重放所有未提交的日志条目,重建状态机。
2.3.2 快照(Snapshot)
随着时间推移,WAL 日志会无限增长。etcd 通过创建快照来压缩日志。快照是某一时刻 BoltDB 状态机数据的完整副本。创建快照后,该时间点之前的所有 WAL 日志都可以安全删除。
| 快照类型 | 触发条件 | 对性能的影响 |
|---|---|---|
| 定期快照 | WAL 文件数量超过 --snapshot-count(默认 100000 条日志) |
创建快照时,BoltDB 需要遍历整个 B+ 树,产生大量磁盘 I/O 和 CPU 消耗,可能导致写延迟抖动。 |
| 手动快照 | 运维人员通过 etcdctl snapshot save 触发 |
用于备份或迁移,同样会消耗大量资源。 |
2.4 架构总览:Raft + WAL + BoltDB 协同工作
下图展示了 etcd 一次写请求的完整数据流,以及 Raft、WAL、BoltDB 三者之间的协作关系。
2.5 关键指标与容量水位评估要点
基于上述架构,在进行多集群容量水位评估时,需要重点关注以下指标:
| 组件 | 关键指标 | 评估阈值参考 | 影响 |
|---|---|---|---|
| Raft | Leader 变化次数、Raft 日志落后量 | Leader 变化 < 0.1 次/分钟;日志落后 < 1000 条 | 频繁选举或日志落后表明网络或磁盘 I/O 存在瓶颈 |
| WAL | WAL 文件总大小、WAL 写入延迟(fsync) | WAL 写入延迟 P99 < 10ms;WAL 文件数 < 100 | 高延迟直接拖慢写吞吐;WAL 文件过多占用磁盘空间 |
| BoltDB | 数据库文件大小、打开读事务数、空闲页比例 | 数据库文件 < 8GB;读事务数 < 100;空闲页 < 20% | 大数据库增加快照时间和内存占用;高读事务数可能阻塞写 |
| 快照 | 快照文件大小、快照创建频率、快照耗时 | 快照耗时 < 30s;快照文件 < 数据文件 1.5 倍 | 快照期间 I/O 压力大,可能导致服务抖动 |