分布式系统学习笔记(二):共识算法 Raft

写在前面

本文讲共识算法(Consensus)——多个节点如何对某个值达成一致。它是 CP 系统(etcd、Zookeeper、TiKV)实现强一致性的核心。重点讲 Raft(比 Paxos 好懂),它是现代分布式系统的共识算法标配。


一、什么是共识问题

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
共识(Consensus):多个节点就某个决议(值)达成一致

典型场景:
  - 选主:哪个节点当 Leader
  - 日志复制:操作的顺序(先 A 后 B,还是先 B 后 A)
  - 状态机复制:所有副本状态一致

难点:
  节点可能宕机
  网络可能丢包/延迟/分区
  没有全局时钟

  但必须保证:
    所有正常节点达成相同决议
    决议一旦达成不可更改
    能容忍少数节点故障

二、Paxos(经典但难懂)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Paxos(Lamport 1998)是共识算法的鼻祖
  数学上严谨、正确
  但极难理解、更难实现

  核心思想:多数派(Quorum)+ 两阶段(Prepare/Accept)
  只要多数节点同意,决议通过

  实际系统很少直接用 Paxos(太复杂)
  多用 Raft(更易懂的等价算法)或 Paxos 变体
  (Doris 用 Paxos 变体、Chubby 用 Paxos、Spanner 用 Paxos)

三、Raft 核心思路

Raft(2013)的设计目标就是"好懂"。它把共识拆成三个子问题:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
1. Leader 选举(Leader Election)
   选出一个 Leader 处理所有请求

2. 日志复制(Log Replication)
   Leader 接收请求,复制到其他节点,多数确认后提交

3. 安全性(Safety)
   保证已提交的日志不被覆盖

核心简化:把"任意节点都可提议"简化为"只有 Leader 提议"
  一切由 Leader 主导,逻辑清晰

3.1 节点状态

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
每个节点三种状态:
  Follower  — 跟随者,被动接收 Leader 指令
  Candidate — 候选者,发起选举
  Leader    — 领导者,处理所有请求

状态转换:
  Follower ──(超时无心跳)──→ Candidate
  Candidate ──(获多数票)──→ Leader
  Candidate ──(发现更高term的Leader)──→ Follower
  Leader    ──(发现更高term)──→ Follower

四、Leader 选举

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
1. 初始都是 Follower
2. 一段时间没收到 Leader 心跳 → 超时
3. Follower 变 Candidate,term+1,给自己投票,发 RequestVote
4. 其他节点收到:
   - 如果 Candidate 日志不比自己旧 → 投票
   - 每个 term 只投一票(先到先得)
5. Candidate 收到多数票 → 成为 Leader
6. Leader 定期发心跳,维持权威

  term(任期)是 Raft 的逻辑时钟:
    单调递增
    每个 term 最多一个 Leader
    term 小的服从 term 大的
1
2
3
避免选主冲突(脑裂):
  随机化选举超时时间(150~300ms 随机)
  避免多个节点同时超时、同时竞选

五、日志复制

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Leader 处理客户端请求的流程:

1. 客户端发请求给 Leader(写命令)
2. Leader 写入本地日志(未提交)
3. Leader 并发发给所有 Follower(AppendEntries)
4. Follower 写入本地日志,回复 ACK
5. Leader 收到「多数」ACK → 提交(commit)
6. Leader 回复客户端「成功」
7. Leader 在下次心跳通知 Follower 提交
8. Follower 提交,状态机应用

  关键:多数(Quorum)确认才提交
  3 节点集群,2 个确认即可(容忍 1 个故障)
  5 节点集群,3 个确认即可(容忍 2 个故障)
1
2
3
4
5
6
7
8
9
Quorum 公式:
  N 个节点,多数 = ⌊N/2⌋ + 1
  可容忍故障 = N - 多数

  3 节点:多数 2,容错 1
  5 节点:多数 3,容错 2
  7 节点:多数 4,容错 3

  常用奇数节点(3/5/7),性价比高

六、安全性保证

Raft 保证几个关键不变式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
1. Leader 完整性
   如果一条日志在某个 term 提交了,
   那它一定存在于所有后续 term 的 Leader 日志中

2. 状态机安全
   所有节点按相同顺序应用相同日志 → 状态一致

3. 选举限制
   投票时,Follower 只投给「日志至少和自己一样新」的 Candidate
   → 保证新 Leader 不会丢已提交日志

  这些不变式保证了:已提交的数据绝不丢、所有副本最终一致

七、脑裂与 Quorum

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
脑裂(Split Brain):网络分区导致两个 Leader

  例:5 节点分区成 3 + 2
  3 那边有多数,能选主、能提交(正常工作)
  2 那边没多数,选不出主 / 无法提交(拒绝服务)

  → Quorum(多数派)天然防止脑裂
  只有拥有多数的分区才能写入,少数分区自动失效

  这就是 CP 系统"分区时牺牲可用性"的体现

八、实际应用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
系统          共识算法        用途
──────────────────────────────────────────────
etcd          Raft           K8s 配置/服务发现
Consul        Raft           服务发现/配置
TiKV          Raft           分布式 KV(TiDB 底层)
CockroachDB   Raft           分布式 SQL
Nacos         Raft(自研)    配置/注册中心
Doris         Paxos 变体      MPP 数据库
Zookeeper     ZAB(Paxos 类) 协调服务
Spanner       Paxos           Google 全球数据库
1
2
3
4
5
6
7
Raft 为什么流行:
  ✓ 好懂(相比 Paxos)
  ✓ 易实现
  ✓ 工程友好(Leader 模型清晰)
  ✓ 强一致性 + 容错

  现代新系统几乎都选 Raft

九、共识 vs 一致性 vs 复制

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
容易混的三个概念:

复制(Replication)
  数据在多节点存副本(手段)
  主从复制、多主复制、无主复制

共识(Consensus)
  多节点就值/顺序达成一致(强一致复制的核心机制)
  Raft、Paxos

一致性(Consistency)
  客户端看到的数据一致性级别(结果)
  强一致、最终一致

  关系:共识算法(Raft)实现强一致的复制(手段),从而提供强一致性(结果)

十、小结

  • 共识:多节点对决议达成一致,容忍少数故障
  • Paxos:鼻祖但难懂;Raft:好懂的等价算法,现代标配
  • Raft 三子问题:Leader 选举、日志复制、安全性
  • 核心机制:Leader 主导 + Quorum(多数确认才提交)+ term(逻辑时钟)
  • 容错:N 节点容忍 ⌊(N-1)/2⌋ 故障,常用 3/5/7 节点
  • 脑裂:Quorum 天然防止,少数分区无法写入
  • 应用:etcd/Consul/TiKV/CockroachDB 等

下一篇讲分布式锁——如何用共识系统/Redis 实现互斥。