2. etcd 存储架构基础:Raft日志、WAL文件、快照与数据库文件的关系
理解 etcd 的存储架构是进行压测调优的前提。etcd 的持久化层由四个核心组件构成:Raft 日志、WAL 文件、快照 (Snapshot) 和 数据库文件 (DB)。它们共同协作,保证了集群的强一致性与数据恢复能力。
2.1 核心组件定义与职责
| 组件 | 存储位置 | 核心职责 | 写入方式 |
|---|---|---|---|
| Raft 日志 | 内存 + WAL | 记录所有状态机变更操作(Put/Delete),用于节点间复制与共识 | 顺序追加 |
| WAL 文件 | 磁盘 (wal 目录) | Raft 日志的持久化载体,确保已提交日志不丢失 | 顺序追加 + fsync |
| 快照 (Snapshot) | 磁盘 (snap 目录) | 压缩 Raft 日志,保存某一时刻的完整状态机数据 | 全量写入 |
| 数据库文件 (DB) | 磁盘 (member/snap/db) | 存储最终的键值数据,基于 BoltDB (etcd v3) 实现 | B+树随机写入 |
关键认知: Raft 日志是“操作记录”,WAL 是日志的“磁盘保险箱”,快照是日志的“压缩包”,DB 文件是最终可查询的“数据仓库”。
2.2 数据写入与持久化流程
一次客户端写入请求在存储层的流转路径如下:
- 提案 (Propose): Leader 节点将写操作封装为 Raft 日志条目。
- 追加到 WAL: 日志条目先顺序写入当前 WAL 文件,并执行
fsync确保落盘。 - 广播与提交: Leader 将日志条目复制给 Follower,多数节点确认后标记为“已提交”。
- 应用到状态机: 已提交的日志条目被应用到内存状态机,并写入 BoltDB 数据库文件。
- 返回客户端: 写入成功响应返回给客户端。
性能要点: 步骤 2 的
fsync 是写入延迟的主要瓶颈。步骤 4 的 BoltDB 写入涉及 B+树分裂与磁盘随机写,是吞吐量的关键限制因素。
2.3 快照与日志压缩机制
随着运行时间增长,Raft 日志会无限膨胀。etcd 通过快照机制进行日志压缩:
- 触发条件: 当 Raft 日志条目数量达到
--snapshot-count阈值(默认 100,000)时,触发快照。 - 快照生成: etcd 将当前内存状态机数据序列化,写入
.snap文件。 - 日志截断: 快照生成后,该快照之前的所有 Raft 日志条目可以被安全删除。
- 恢复流程: 新节点加入或节点崩溃恢复时,先加载最近的快照,再重放快照之后的少量 WAL 日志。
调优陷阱: 快照频率过高(
--snapshot-count 过小)会导致频繁的全量磁盘 I/O,影响写入性能;频率过低则导致 WAL 日志文件过大,延长节点恢复时间。
2.4 快照与 WAL 的协同恢复流程
当 etcd 节点重启或新节点加入时,恢复顺序至关重要:
- 加载快照: 从 snap 目录读取最新的
.snap文件,将状态机恢复到快照时刻。 - 重放 WAL: 从快照对应的索引位置开始,顺序读取并重放 WAL 文件中的后续日志条目。
- 追赶进度: 如果 WAL 中仍有缺失,Leader 会通过 Raft 协议将缺失的日志条目发送给该节点。
恢复时间估算: 恢复时间 ≈ 快照加载时间 + (WAL 日志量 / 重放速率)。快照频率越高,WAL 日志量越少,恢复越快,但快照生成时的性能开销越大。
2.5 性能调优关联点
理解上述关系后,压测调优的核心平衡点在于:
- 快照频率 (
--snapshot-count): 控制 WAL 日志保留量,直接影响磁盘空间占用和恢复速度。 - WAL fsync 策略: 每次写入都 fsync 保证强一致性,但也是延迟的主要来源。
- DB 文件 compaction: 历史版本数据的清理策略,影响 DB 文件大小和查询性能。
- 磁盘 I/O 隔离: WAL 的顺序写与 DB 的随机写共享磁盘带宽,建议使用独立磁盘或高性能 SSD。