9.3 共识与一致性:多个节点如何达成一致
核心问题:多个节点如何在没有全局状态的情况下达成一致?
开场问题:分布式配置管理
你负责一个分布式系统,配置需要同步到100台机器。
简单想法:主节点修改配置,广播给所有节点。
问题场景:
时刻1:主节点修改配置为v2,准备广播
时刻2:主节点向节点1-50发送v2
时刻3:主节点网络故障,未向节点51-100发送
时刻4:节点1-50配置为v2,节点51-100配置为v1
结果:系统状态不一致,节点行为混乱困惑:为什么"简单的广播"失效了?
答案:因为没有可靠的全局状态,节点可能收到不同的消息。
共识问题定义
形式定义
共识问题:n个节点,每个节点有初始值,需要达成一致的最终值。
要求:
- 一致性(Agreement):所有正确节点达成相同值
- 有效性(Validity):达成值是某个节点的初始值
- 终止性(Termination):所有正确节点最终达成一致
挑战
异步环境下不可能(FLP不可能性定理):
在完全异步模型下(无消息延迟上限、无时钟同步),即使只有一个节点可能失败,也不存在确定性共识算法。
解决:引入假设
- 部分同步:存在消息延迟上限
- 随机化:用随机算法绕过FLP
- 失败检测:假设能检测失败节点
Paxos:经典共识算法
核心思想
Paxos:Leslie Lamport发明的经典共识算法。
核心思想:
- 多轮投票,多数同意即通过
- Proposer提议,Acceptor投票,Learner学习结果
三种角色
Proposer:提议者
- 发起提案(提议某个值)
- 向Acceptor发送Prepare和Accept请求
Acceptor:投票者
- 接收Proposer的提案
- 投票同意或拒绝
Learner:学习者
- 从Acceptor获取结果
- 学习达成一致的值两阶段协议
阶段1:Prepare
Proposer → Acceptor: Prepare(n) # n是提案编号
Acceptor收到Prepare(n):
if n > 已承诺的最大编号:
承诺不再接受编号<n的提案
返回 Promise(n, 已接受的值)
阶段2:Accept
Proposer收到多数Promise:
if 收到的Promise有已接受的值:
提议该值(尊重之前的决定)
else:
提议自己的值
→ Acceptor: Accept(n, 值)
Acceptor收到Accept(n, 值):
if n >= 已承诺的最大编号:
接受该值
返回 Accepted(n, 值)类比:议会表决
想象议会投票:
- Proposer提出法案
- Acceptor是议员
- 多数议员同意 → 法案通过
- 如果两个Proposer同时提案 → 编号大的优先
Raft:简化共识算法
为什么Raft更简单?
Paxos的问题:难理解、难实现。
Raft的设计目标:易于理解。
核心思想:
- 分解问题:领导者选举 + 日志复制 + 安全性
- 领导者驱动:简化决策流程
三种角色
Leader:领导者
- 处理所有客户端请求
- 向Follower发送日志
Follower:跟随者
- 接收Leader的日志
- 响应Leader的请求
Candidate:候选人
- 选举时竞选Leader领导者选举
超时触发选举:
Follower未收到Leader心跳 → 被选举超时
Candidate发起选举:
1. 增加任期号
2. 向所有节点请求投票
3. 收到多数投票 → 成为Leader
4. 开始发送心跳日志复制
客户端请求 → Leader:
1. Leader追加日志条目
2. 向Follower发送AppendEntries RPC
3. 等待多数Follower确认
4. 应用日志到状态机
5. 响应客户端安全性保证
日志匹配性质:
如果两个日志在同一任期、同一索引有相同条目
→ 它们之前的所有条目都相同
领导者完整性:
新Leader必须包含所有已提交的日志类比理解共识
团队决策类比
共识像团队投票表决:
场景:团队需要决定午餐吃什么
朴素方案:
每人同时提议 → 可能多个提议同时存在
→ 混乱,无法决定
Paxos方案:
某人提议(编号1):吃火锅
多数人同意 → 决定吃火锅
某人提议(编号2):吃日料
多数人发现编号1已决定 → 遵守编号1的决定
Raft方案:
先选组长 → 组长决定吃什么
组员跟随组长 → 简单高效为什么需要多数?
原因:少数节点可能失败或被隔离。
节点1-5:
节点1-3同意值A → 达成一致
节点4-5网络隔离 → 不知道结果
但节点1-3占多数 → 值A已决定
如果节点4后来恢复:
它发现多数已决定A → 遵守A共识的应用场景
1. 分布式配置管理
配置更新:
Leader接收配置修改请求
→ 复制到多数节点
→ 配置生效
好处:
- 所有节点配置一致
- 容错(少数节点失败不影响)2. 分布式锁
锁服务:
客户端请求锁 → Leader分配锁
Leader记录锁状态 → 复制到多数节点
锁被持有,其他客户端等待
好处:
- 锁状态一致
- 容错(Leader失败 → 选举新Leader)3. 分布式事务
事务提交:
节点执行事务 → 投票是否提交
多数同意 → 事务提交
否则 → 事务回滚
好处:
- 所有节点事务状态一致
- 容错共识的成本
通信成本
每次共识需要:
- Proposer → Acceptor:发送Prepare
- Acceptor → Proposer:返回Promise
- Proposer → Acceptor:发送Accept
- Acceptor → Learner:返回Accepted
轮数:至少2轮
消息数:O(n²)(每个Proposer要联系所有Acceptor)
性能影响
共识成本高 → 不适合频繁操作。
优化:
- 批量共识:一次共识多个值
- Leader缓存:Leader直接处理,减少共识频率
- 异步共识:先执行,后台共识
LLM视角:共识的应用
LLM多Agent协作
场景:多个Agent协作完成复杂任务。
挑战:
Agent A提议方案1
Agent B提议方案2
如何达成一致?
解决:
用共识机制:
- 某Agent作为Leader
- 其他Agent跟随Leader决策
- 容错:Leader失败 → 选举新Leader分布式推理协调
场景:分布式推理需要协调各节点。
挑战:
模型分布在多节点
推理结果需要一致
解决:
用共识保证:
- 所有节点推理状态一致
- 容错机制小结
核心概念
| 概念 | 定义 | 作用 |
|---|---|---|
| 共识问题 | 多节点达成一致 | 保证系统一致性 |
| Paxos | 经典共识算法 | 多数投票机制 |
| Raft | 简化共识算法 | 领导者驱动,易理解 |
| 多数决策 | >半数节点同意 | 容错保证 |
设计要点
- 领导者选举:简化决策流程
- 日志复制:保证一致性
- 多数决策:容错保证
- 成本权衡:共识代价高,不适合频繁操作
LLM视角
共识在LLM时代有新应用:
- 多Agent协作决策
- 分布式推理协调
- 分布式训练状态同步
练习
1. 模拟Raft选举
场景:5个节点,节点1是Leader。
- 节点1网络故障 → 触发选举
- 模拟选举流程,谁会成为新Leader?
2. 分析共识成本
场景:100个节点,用Raft达成一次共识。
计算需要的消息数和轮数。
3. 设计多Agent共识
场景:3个Agent协作,需要决定执行哪个任务。
设计共识机制,保证Agent决策一致。
下一节
理解了共识机制后,我们来看一致性级别: