2. etcd 核心概念回顾:Raft 共识算法、Leader 选举、日志复制、仲裁机制

在深入多租户仲裁水位隔离策略之前,必须重新校准对 etcd 底层共识引擎的理解。etcd 使用 Raft 共识算法 来保证分布式系统中的强一致性与高可用性。本节将拆解 Raft 的核心组件:Leader 选举、日志复制与仲裁(Quorum)机制,并阐明它们如何共同决定 etcd 集群的容错边界。

2.1 Raft 共识算法概述

Raft 是一种易于理解的分布式共识算法,它将共识问题分解为三个相对独立的子问题:Leader 选举、日志复制 和 安全性。在 etcd 中,Raft 确保所有节点(Member)的状态机以相同的顺序执行相同的命令,从而达成最终一致。

核心原则: 只要集群中超过半数(N/2 + 1)的节点存活且相互通信正常,etcd 集群就能对外提供一致的读写服务。这个半数阈值就是 仲裁(Quorum)。

2.2 Raft 节点角色与状态转换

每个 etcd 节点在任意时刻都处于以下三种角色之一:

角色 职责 关键行为
Leader(领导者) 处理所有客户端请求(读写),管理日志复制,发送心跳。 定期向 Follower 发送 AppendEntries(心跳 + 日志);处理写请求时,必须等待多数节点确认。
Follower(跟随者) 被动响应 Leader 和 Candidate 的请求,不主动发起任何操作。 接收并应用来自 Leader 的日志条目;如果超时未收到 Leader 心跳,则转换为 Candidate。
Candidate(候选者) 发起 Leader 选举,争取成为新的 Leader。 增加任期号(Term),向其他节点请求投票;获得多数票后成为 Leader。
术语提示: 任期号(Term)是 Raft 中的逻辑时钟,每次选举开始都会递增。一个任期内最多只有一个 Leader。
Raft 节点角色状态转换图 Follower Candidate Leader 选举超时 获得多数票 发现更高任期 / 网络分区恢复 选举超时 / 发现合法 Leader 状态转换由选举超时(Election Timeout)和任期号(Term)驱动

2.3 Leader 选举机制

当 Follower 在 选举超时时间(通常为 150ms ~ 300ms 随机)内未收到 Leader 的心跳,它会认为 Leader 已宕机,从而触发新一轮选举:

  1. 发起选举: Follower 增加本地任期号(Term+1),转换为 Candidate,并投票给自己。
  2. 请求投票: Candidate 并行向集群中所有其他节点发送 RequestVote RPC。
  3. 投票规则: 每个节点在一个任期内只能投出一票,且优先投票给日志更完整(Term 更大、Log Index 更长)的 Candidate。
  4. 胜出条件: Candidate 获得超过半数(N/2 + 1)的投票后,成为新的 Leader。
  5. 平局处理: 如果多个 Candidate 均未获得多数票,选举失败,所有 Candidate 等待随机超时后重新发起选举。
关键影响: 频繁的 Leader 选举会降低集群可用性。在 etcd 运维中,网络抖动或磁盘 I/O 延迟过高都可能导致不必要的选举,进而引发短暂的“无 Leader”窗口期。

2.4 日志复制(Log Replication)

一旦 Leader 当选,它开始负责处理所有客户端写入请求。日志复制流程如下:

步骤 操作描述 关键状态
1. 追加 Leader 将客户端请求封装为日志条目(Entry),追加到本地日志。 日志条目包含:Term、Index、Command。
2. 并行发送 Leader 通过 AppendEntries RPC 并行将日志条目发送给所有 Follower。 RPC 包含前一条日志的 Index 和 Term,用于一致性检查。
3. 接收与确认 Follower 检查日志一致性后追加到本地日志,并回复确认。 如果日志不一致,Follower 拒绝并返回冲突信息,Leader 回退重试。
4. 提交(Commit) Leader 收到多数节点(Quorum)的确认后,将日志条目标记为已提交。 Leader 将提交索引(Commit Index)通过后续心跳广播给所有 Follower。
5. 应用(Apply) 所有节点将已提交的日志条目应用到状态机(如 etcd 的 KV 存储)。 应用顺序与日志顺序完全一致,保证状态机确定性。
etcd Raft 日志复制流程 Client PUT /key Leader 追加日志到本地 Log[Term=3, Index=5] AppendEntries AppendEntries AppendEntries Follower 1 Follower 2 Follower 3 Quorum 确认 3/5 → 提交 广播 Commit Index 给所有 Follower 只有被 Quorum 确认的日志条目才会被提交并应用到状态机

2.5 仲裁(Quorum)机制与容错模型

仲裁是 Raft 算法的核心安全阀。它定义了集群能够容忍的最大故障节点数。对于一个包含 N 个节点的 etcd 集群:

  • 仲裁大小(Quorum Size): Q = N/2 + 1(向下取整)。
  • 最大故障容忍数(Fault Tolerance): F = N - Q = (N-1)/2(向下取整)。
  • 写操作: 必须等待至少 Q 个节点(包括 Leader)确认日志写入,才能返回客户端成功。
  • 读操作(线性一致性读): 默认也需要经过 Quorum 确认(通过 ReadIndex 或 Lease Read),以确保读取到已提交的最新数据。
集群节点数 (N) 仲裁大小 (Q) 最大故障容忍数 (F) 典型场景
1 1 0 开发/测试,无高可用
3 2 1 生产最小推荐配置
5 3 2 生产标准高可用配置
7 4 3 超大规模或跨区域部署
多租户关联: 在 Serverless 控制面中,每个租户的请求最终都会转化为 etcd 的写入操作。如果某个 etcd 节点因为租户流量过载(如大量 Watch 请求或高并发写入)而变慢,它可能无法及时响应 Leader 的 AppendEntries 心跳,导致 Leader 认为该节点已失效。当故障节点数超过 F 时,集群将失去仲裁能力,所有租户的读写都会中断。这正是我们引入“仲裁水位隔离策略”的原始动机——通过控制每个租户对 etcd 仲裁资源的消耗,防止单一租户的行为导致全局仲裁失效。

2.6 安全性保证:为什么仲裁如此重要

Raft 的安全性建立在以下关键属性上,这些属性都依赖于仲裁机制:

  • Election Safety: 在一个任期内,最多只有一个 Leader 被选出(通过多数票保证)。
  • Leader Append-Only: Leader 从不覆盖或删除自己的日志,只追加新条目。
  • Log Matching: 如果两个节点上的日志条目具有相同的 Index 和 Term,那么这两个条目及其之前的所有条目都完全相同。
  • Leader Completeness: 被提交的日志条目在后续所有 Leader 任期中都一定存在(新 Leader 必须包含所有已提交的日志)。
  • State Machine Safety: 所有节点以相同的顺序应用相同的日志条目,保证状态机一致。
实践建议: 在生产环境中,始终使用奇数节点数(3、5、7)。偶数节点(如 4 节点)的容错能力与比它小 1 的奇数节点相同(4 节点容忍 1 故障,3 节点也容忍 1 故障),但增加了运维复杂度和网络开销。