2. etcd 架构速览:Raft共识组、存储引擎、网络层组件与数据流路径

在深入压测参数调优之前,必须建立 etcd 内部架构的清晰认知。etcd 是一个强一致、高可用的分布式键值存储系统,其核心由三个逻辑层构成:共识层(Raft)、存储引擎层(boltdb / backend) 和 网络层(gRPC / HTTP)。理解这三层之间的数据流路径,是定位性能瓶颈、平衡网络带宽与消息大小的前提。

2.1 三层架构总览

下图展示了 etcd 进程内部的主要组件及其协作关系。客户端请求从网络层进入,经过 Raft 共识组达成一致后,最终写入持久化存储。

etcd 三层架构与数据流路径 网络层 — gRPC Server / HTTP Gateway gRPC API HTTP Gateway Watch Stream Auth 共识层 — Raft Consensus Group Raft Node (Leader) Propose / Commit Raft Node (Follower) Append / Apply Raft Node (Follower) Append / Apply 存储引擎层 — Backend / boltdb boltdb (B+树) 持久化 KV 数据 WAL (预写日志) 顺序写入磁盘 Snapshot 全量快照 数据流方向:Client → gRPC → Raft Leader → 广播至 Followers → 持久化到 boltdb + WAL

2.2 网络层组件

网络层是客户端与 etcd 集群交互的第一道关口。etcd 同时暴露 gRPC 和 HTTP/JSON 两种 API 接口,但内部核心通信全部基于 gRPC。

组件 协议 主要职责 压测关注点
gRPC API HTTP/2 + Protobuf 处理 KV 读写、Watch、Lease 等核心 RPC 消息序列化大小、流控、连接数
HTTP Gateway HTTP/1.1 + JSON 提供 RESTful 兼容接口,内部转为 gRPC JSON 序列化开销、额外带宽消耗
Watch Stream gRPC Server-Sent Stream 推送键值变更事件给客户端 事件大小、推送频率、背压机制
Auth 中间件 拦截器 认证、鉴权、TLS 终止 TLS 握手开销、证书验证延迟
压测启示: 在压测场景中,gRPC 的 Protobuf 编码 比 HTTP Gateway 的 JSON 编码节省约 30%~50% 的带宽。如果压测目标聚焦网络带宽瓶颈,应优先使用 gRPC 客户端(如 etcdctl 或自定义 gRPC 压测工具),避免 JSON 序列化带来的额外开销。

2.3 Raft 共识组

Raft 是 etcd 的“大脑”,负责在多个节点之间复制日志并保证强一致性。一个 etcd 集群通常由 3 或 5 个节点 组成,每个节点运行一个 Raft 状态机。

2.3.1 Raft 节点角色

  • Leader(领导者):处理所有客户端写入请求,将日志条目复制到 Follower,负责日志提交。
  • Follower(跟随者):被动接收 Leader 的日志复制,响应投票请求,处理只读查询(可转发至 Leader)。
  • Candidate(候选者):Leader 失效时发起选举,争取成为新 Leader。

2.3.2 写入路径中的 Raft 流程

一次成功的写入请求在 Raft 层经历以下步骤:

  1. Propose:Leader 收到客户端写入请求,将操作封装为 Raft Log Entry。
  2. Append:Leader 将 Log Entry 并行发送给所有 Follower(通过 gRPC 的 RaftMessage 流)。
  3. Persist:每个节点将 Log Entry 写入本地的 WAL(预写日志)。
  4. Commit:Leader 收到多数派(Quorum)的确认后,标记该 Entry 为已提交。
  5. Apply:Leader 将已提交的 Entry 应用到状态机(即写入 boltdb),并响应客户端。
带宽敏感点: 步骤 2 中,Leader 向所有 Follower 发送的 RaftMessage 包含完整的请求数据。消息大小越大,网络带宽消耗呈线性增长。在 3 节点集群中,一次写入会产生 1 次客户端→Leader + 2 次 Leader→Follower 的网络传输,总带宽消耗约为请求大小的 3 倍(不考虑心跳和确认包)。

2.4 存储引擎层

etcd 的存储引擎分为 内存状态机 和 持久化存储 两部分。持久化存储由 boltdb 和 WAL 共同构成。

组件 存储位置 数据结构 写入方式 压测影响
boltdb 磁盘文件(如 member/snap/db) B+ 树 随机写入 + 页缓存 大 value 导致 B+ 树分裂,增加磁盘 IO
WAL 磁盘文件(如 member/wal/) 顺序追加日志 顺序写入 + fsync 大消息增加单条日志大小,影响 fsync 频率
Snapshot 磁盘文件(如 member/snap/) 全量 boltdb 快照 定期生成,压缩传输 快照过大占用带宽,影响集群恢复时间

2.5 完整数据流路径(写入场景)

下图聚焦一次 Put 请求 在 etcd 内部的完整数据流,展示消息大小如何影响每一层的处理开销。

Put 请求完整数据流路径 ① Client 发送 Put gRPC Request ② Leader 接收 反序列化 + 鉴权 ③ Propose 日志 Raft Log Entry ④ 广播至 Follower RaftMessage 流 ⑤ 多数派确认 Quorum Ack ⑥ 写入 WAL 顺序 fsync ⑦ Apply 到 boltdb B+ 树写入 ⑧ 响应 Client gRPC OK 带宽消耗关键点 步骤 ① ③ ④ 涉及网络传输 消息大小直接影响带宽占用 消息大小影响范围 序列化时间、网络延迟、磁盘 IO Raft 日志复制延迟、吞吐量

2.6 关键性能指标与压测映射

将架构组件与压测指标对应,有助于后续章节的参数调优:

架构层 关键组件 压测指标 消息大小影响
网络层 gRPC / HTTP 吞吐量 (ops/s)、延迟 (p99)、带宽 (MB/s) 大消息降低 ops/s,增加带宽占用
共识层 Raft Leader → Follower Raft 日志复制延迟、选举时间 大消息增加复制延迟,极端情况触发选举超时
存储层 boltdb / WAL 磁盘 IOPS、fsync 耗时、B+ 树分裂频率 大 value 导致 B+ 树深度增加,WAL 单条变大
常见误区: 很多压测者只关注客户端侧的吞吐量,忽略了 Raft 层内部复制带来的带宽放大效应。在 5 节点集群中,一次 1MB 的写入请求,实际网络传输量约为 1MB (Client→Leader) + 4MB (Leader→4 Followers) = 5MB。如果集群跨机房部署,带宽瓶颈会首先在 Leader 的上行链路暴露。

2.7 本章小结