3. 一致性算法(Raft / Paxos)

章节导入

一致性算法是分布式存储面试中的"分水岭"题。Raft 以"可理解性"成为面试首选,Paxos 考察理论深度。本章精讲选举、日志复制、安全性三大核心,并拆解常见误区,帮你构建"原理 + 工程"双线回答体系。

回答框架:一致性算法 Leader 选举机制 日志复制流程 安全性保证 任期与超时 投票规则 脑裂避免 AppendEntries 多数派提交 日志匹配 选举安全性 Commitment 领导者追加 加分点:面试中主动补充 Multi-Paxos 与 Raft 的异同 以及实际工程中的成员变更优化(如单节点变更)
核心记忆链:
Raft = 强 Leader + 任期 + 日志连续性 + 多数派确认。
Paxos = Prepare → Promise → Accept → Accepted(Basic Paxos),Multi-Paxos 通过选主优化。

面试问答卡片

Q1:请解释 Raft 的 Leader 选举过程,并说明如何避免脑裂?

考察点 对分布式共识基本机制的理解,是否关注超时、任期、投票分裂等工程细节。
回答框架 ① 任期单调递增 → ② Follower 超时转为 Candidate → ③ 发起 RequestVote → ④ 获得多数票 → ⑤ 成为 Leader 并发送心跳 → ⑥ 脑裂通过任期和日志新旧来杜绝。
示例回答 “Raft 选举基于随机超时和任期。Follower 在选举超时内未收到心跳,递增任期并自荐为 Candidate,向所有节点投票。获得过半票数后成为 Leader,开始定期发送心跳。脑裂时,旧 Leader 会因任期落后而自动降级,保证最多一个有效 Leader。”
可能追问 ① 如果两个 Candidate 同时发起选举,票数相同怎么办?② 新的 Follower 加入集群时,选举会发生什么?
避坑提醒 不要只背“随机超时”一句话。要说明投票规则:Candidate 的日志必须不比 Follower 旧才能获得该 Follower 的投票,这是安全性的关键。

Q2:Raft 如何保证日志复制的一致性?如果出现日志不一致怎么处理?

考察点 对日志条目、commit 规则、Leader 强制覆盖机制的理解。
回答框架 ① Leader 接收客户端请求,追加本地日志 → ② 并行 AppendEntries 到所有 Follower → ③ 多数派确认后 Leader 在下一轮心跳中 commit → ④ 不一致时 Leader 从最新索引向前逐项比对 → ⑤ 强制 Follower 覆盖不一致条目。
示例回答 “Raft 要求所有 Follower 的日志必须与 Leader 一致。Leader 在 AppendEntries 中携带前一条日志的 term 和 index,Follower 检查匹配后才接受。一旦发现冲突,Leader 逐步后退直到找到共同匹配点,然后删除后续日志并用 Leader 日志替换。只有当日志被多数节点复制后才可 commit。”
可能追问 ① 为什么 Raft 只允许 Leader 提交当前任期的日志?② 如果 Follower 日志比 Leader 还多,会怎样?
避坑提醒 不要混淆“复制”和“提交”。多数派复制 ≠ 提交,必须等待当前任期的日志被 Leader 在下一心跳中正式 commit 才算生效。旧任期的日志通过当前任期日志间接提交。

Q3:Raft 和 Paxos 核心区别是什么?什么场景更适合用 Raft?

考察点 对两种算法设计哲学的理解,以及工程选型能力。
回答框架 ① 设计目标不同:Paxos 侧重理论证明,Raft 侧重可理解性 → ② 角色模型:Paxos 无强 Leader,Raft 用强 Leader → ③ 日志流:Raft 保证日志连续性,Paxos 允许乱序 → ④ 成员变更复杂性:Raft 有联合共识或单节点变更 → ⑤ 选型建议:需要快速实现、运维友好的系统选 Raft。
示例回答 “Paxos 更抽象,Multi-Paxos 在工程上常引入类似 Raft 的选主机制。Raft 明确将算法拆解为选举、日志复制、安全性三大模块,且强制日志连续性,极大简化实现。在 etcd、Consul 等系统中广泛采用。如果团队需要快速开发且运维复杂度低,Raft 是首选。”
可能追问 ① Raft 能否保证线性一致性?需要额外措施吗?② Basic Paxos 和 Multi-Paxos 的区别?
避坑提醒 不要简单说“Paxos 难懂,Raft 易懂”。面试官期望你指出 Paxos 在理论上的优雅(最小多数派、无阻塞),而 Raft 在工程可实施性上的优势。同时承认 Multi-Paxos 在工业界也有成功案例(如 Google Chubby)。

项目案例章节

项目模板:基于 Raft 的分布式键值存储系统

项目名称 RaftKV – 高可用分布式 Key-Value 存储引擎
业务背景 为微服务提供强一致的配置中心+分布式锁底座,要求故障转移时无缝切换,数据不丢失。
规模指标 5 节点集群;QPS 峰值 50k;平均延迟 < 5ms;数据量 2TB;单节点崩溃后恢复时间 < 5s。
技术栈 Go(核心 Raft 实现)、gRPC(节点间通信)、RocksDB(底层存储)、etcd 库(借鉴的 Raft 算法逻辑)。
核心难点 ① 日志复制过程中网络分区导致 Leader 切换后的数据一致性校验;② 大规模成员变更时避免性能抖动;③ 快照调优:RocksDB snapshot 与 Raft snapshot 的同步策略。
面试高频追问 ① 如何保证 Leader 切换时不丢已提交的数据?② 快照生成时怎么做增量同步?③ 你们自己实现 Raft 还是用 etcd 库?为什么?
可迁移回答话术 “我们在项目中采用了强 Leader 模型,所有读写必须经过 Leader。Leader 切换时,新 Leader 通过比对日志条目 term 和 index 来确认 committed 状态,然后应用快照。成员变更则使用单节点变更方法,逐台添加/移除节点,避免联合共识的复杂逻辑。”
面试加分技巧:当被问及项目经验时,主动指出“Raft 的选举超时参数我们根据网络延迟调整为了 100-200ms 的随机范围”,体现工程细节敏感度。
常见致命误区:回答 Raft 日志复制时,忘记提及“日志匹配属性(Log Matching Property)”,导致面试官质疑对安全机制的理解是否完整。务必强调:Leader 日志索引与 term 的二元组唯一确定一个日志条目。