1. etcd 架构概述:Raft 共识算法、存储引擎与 WAL 日志
etcd 是一个高可用的分布式键值存储系统,其核心架构围绕 一致性、持久性 和 高可用性 设计。理解其底层三大支柱——Raft 共识算法、bbolt 存储引擎以及 WAL 日志与快照机制,是进行存储性能调优的前提。
1.1 Raft 共识算法:分布式一致性的基石
Raft 是一种用于管理复制日志的共识算法,它将分布式一致性问题分解为三个相对独立的子问题:领导者选举、日志复制 和 安全性。etcd 使用 Raft 确保集群中所有节点数据最终一致。
核心角色:
- Leader(领导者): 负责处理所有客户端请求,并将日志条目复制到 Follower。
- Follower(跟随者): 被动接收来自 Leader 的日志复制请求和心跳,保持数据同步。
- Candidate(候选者): 当 Follower 超时未收到心跳时,转变为 Candidate 并发起选举。
Raft 通过 Term(任期) 和 心跳机制 维持集群稳定。每次写入操作必须经过 Leader 确认,并复制到多数节点(Quorum)后才算提交成功。这一过程直接受网络延迟影响。
1.2 存储引擎:bbolt(BoltDB)
etcd v3 使用 bbolt(BoltDB 的增强分支)作为底层持久化存储引擎。bbolt 是一个基于 B+ 树 的嵌入式键值数据库,它将数据直接写入磁盘文件,而非依赖操作系统页缓存。
| 特性 | 说明 | 性能影响 |
|---|---|---|
| B+ 树索引 | 所有键值对按字典序存储在 B+ 树叶子节点中 | 范围查询高效,但随机写入可能触发页分裂 |
| 事务支持 | 支持读事务(快照隔离)和写事务(串行化) | 写事务独占锁,长事务会阻塞其他写入 |
| 内存映射文件(mmap) | 将数据文件映射到进程地址空间,加速读取 | 读性能接近内存,但写操作仍需系统调用 |
| 无 WAL 内置 | bbolt 自身不提供预写日志,依赖 etcd 的 WAL | etcd 必须保证 WAL 先于数据写入 |
性能调优要点: bbolt 的写性能高度依赖磁盘 IOPS(每秒输入输出操作数)和 fsync 延迟。每次事务提交都会触发一次 fsync,因此磁盘的随机写入能力直接决定 etcd 的写入吞吐上限。
1.3 WAL 日志与快照:持久性与恢复的保障
etcd 使用 WAL(Write-Ahead Logging,预写日志) 和 快照(Snapshot) 来保证数据的持久性和快速恢复能力。
WAL 日志
- 顺序写入: 所有 Raft 日志条目(包括客户端请求)先追加写入 WAL 文件,再应用到 bbolt 存储引擎。
- 崩溃恢复: 节点重启时,通过回放 WAL 日志重建内存状态和 bbolt 数据。
- 磁盘 IO 模式: WAL 是典型的顺序追加写,对 HDD 友好,但 fsync 频率仍影响延迟。
快照(Snapshot)
- 压缩机制: 当 WAL 日志大小超过阈值(默认 10,000 条),etcd 会生成一个快照,将当前状态持久化到 bbolt,并清理旧的 WAL 文件。
- 加速恢复: 新节点加入或崩溃恢复时,先加载快照,再回放少量增量 WAL,大幅缩短恢复时间。
- IO 开销: 快照生成涉及全量数据扫描和写入,可能造成瞬时 IO 压力。
1.4 三者协同关系
etcd 的写入路径清晰地展示了 Raft、WAL 和 bbolt 的协作:
- 客户端请求 发送给 Leader。
- Leader 将请求封装为 Raft 日志条目,并追加到本地的 WAL 文件(顺序写 + fsync)。
- Leader 并行将日志条目复制到 Follower 节点(网络 IO)。
- 当多数节点(Quorum)确认写入 WAL 后,Leader 将日志条目 应用到 bbolt 存储引擎(随机写 + fsync)。
- Leader 返回成功响应给客户端。