853 字
4 分钟
Raft 共识算法详解:Etcd 如何守护 Kubernetes 的大脑

为什么我们需要共识?#

在分布式系统中,最难的问题不是“如何计算”,而是“如何达成一致”。 当你有 3 台服务器(节点),其中一台说 x=1,另一台说 x=2,谁是对的? 如果没有共识算法,Kubernetes 的大脑(Etcd)就会精神分裂,整个集群就会崩溃。

Paxos 曾是唯一的真理,但它太难懂了(连作者自己都承认)。 Raft 的出现,就是为了 可理解性 (Understandability)


一、Raft 的三个子问题#

Raft 将共识问题分解为三个独立的子问题:

  1. Leader Election(领导者选举):谁说了算?
  2. Log Replication(日志复制):如何把指令同步给小弟?
  3. Safety(安全性):如何保证已提交的数据不丢失?

1.1 领导者选举 (Leader Election)#

Raft 节点有三种状态:Follower(跟随者)、Candidate(候选人)、Leader(领导者)。

  • 心跳机制:Leader 必须不断向 Follower 发送心跳(AppendEntries RPC,哪怕是空的)。
  • 选举超时 (Election Timeout):如果 Follower 在一段时间内(比如 150-300ms 随机)没收到心跳,它就认为 Leader 挂了。
  • 发起投票
    1. Follower 变成 Candidate。
    2. Term(任期)加 1。
    3. 给自己投一票。
    4. 向其他节点广播 RequestVote RPC。

谁能当选? 获得 大多数 (Majority) 选票的节点当选。 如果有两个 Candidate 同时发起,票数瓜分(Split Vote),谁都不过半? Raft 利用 随机超时时间 巧妙解决了这个问题。下次选举,总有一个跑得快。

1.2 日志复制 (Log Replication)#

一旦 Leader 确立,客户端的所有写请求都发给 Leader。

  1. Leader 把指令(如 SET x=1)追加到自己的 Log。
  2. Leader 并行发送 AppendEntries RPC 给所有 Follower。
  3. Follower 收到并写入本地 Log,返回 Success。
  4. 提交 (Commit):当 Leader 收到 大多数 Follower 的成功响应,它就将该日志条目标记为 Committed,并应用到状态机(State Machine)。
  5. Leader 告诉客户端:写入成功。

关键点:只要日志被 Committed,它就永远不会丢失(除非大多数节点永久损坏)。


二、安全性与脑裂 (Brain Split)#

如果网络分区了怎么办? 比如 5 个节点(A, B, C, D, E)。 网络把它们切成了 [A, B][C, D, E]

  • 旧 Leader A 在小分区。它收不到大多数的心跳响应,无法提交新日志。
  • 大分区 [C, D, E] 会选出新 Leader C。
  • 客户端连到 C,写入成功(因为 C 有 3 票,过半)。
  • 客户端连到 A,写入会一直阻塞或失败。

当网络恢复时: A 发现 C 的 Term 更大,A 自动退位变成 Follower。 A 会从 C 那里同步最新的日志,自己未提交的旧日志会被覆盖。 结论:Raft 永远保证强一致性 (Strong Consistency)。


三、Etcd 实战优化#

Etcd 使用了 Raft,但做了很多工程优化:

  1. 预投票 (Pre-Vote):Candidate 在发起正式选举前,先问问大家“你们觉得我能行吗?”防止网络抖动的节点频繁打断集群。
  2. 批处理 (Batching):把多个写请求合并成一个网络包发送。
  3. Pipeline:Leader 不等待上一个 RPC 返回就发送下一个。

总结#

Raft 不是魔法,它是严格的逻辑推演。 理解了 Raft,你就理解了为什么 K8s 需要奇数个 Master 节点,为什么 Etcd 对磁盘延迟那么敏感(写日志要 fsync)。 在这个不确定的世界里,Raft 给了我们确定的答案。

Raft 共识算法详解:Etcd 如何守护 Kubernetes 的大脑
https://www.oferry.com/posts/a61/
作者
晨平安
发布于
2026-02-10
许可协议
CC BY-NC-SA 4.0
封面
示例歌曲
示例艺术家
封面
示例歌曲
示例艺术家
0:00 / 0:00