Raft 算法是什么?Leader 选举、日志复制和多数派提交怎么理解?
下面是一段教学用的模拟面试。
🧑💻 面试官:Raft 怎样让多个节点得到一致结果?
🙋♂️ 我:先选一个 Leader,再把数据复制到其他节点。
🧑💻 面试官:Leader 本地写完,就可以向客户端说成功吗?
🙋♂️ 我:不行,需要满足多数派等提交规则。
🧑💻 面试官:五个节点,Leader 加一个 Follower 确认,够吗?新 Leader 拿到旧任期日志,又能只数一下副本就提交吗?
Raft 不是“找个人说了算”。关键是:「谁能当 Leader」,以及「哪条日志已经安全到可以提交」。
面试速答(60 秒版)
Raft 是管理复制日志的共识算法,把 Leader 选举、日志复制和安全约束分别组织起来,让节点按一致的已提交命令推进状态机。
节点主要有 Follower、Candidate、Leader 三种角色,用 term 区分任期。Follower 等不到有效 Leader 联系时,可以启动新任期选举;Candidate 需要取得多数派选票,还要符合日志新旧等投票限制。
Leader 接收命令,记录日志并复制。固定五节点集群的多数派是三个,包含 Leader 自己;本地落一份加一个 Follower,不够。
提交也不只是随便数副本。Leader 通过多数派复制推进提交时,必须遵守当前任期日志等安全规则;已提交前缀再按顺序应用到状态机。
Raft 针对非拜占庭故障模型,不负责任意恶意节点。失去多数派时,不能继续安全提交新日志;客户端重试去重与线性一致读,也还需要配套机制。

知识点详解:用五个节点,看谁能决定一次修改
先明确,它们复制的是一条有序命令日志
假设五个节点共同维护一个配置状态机,客户端要求把 timeout 改成 5。
Raft 组织的核心是命令日志:每条记录有位置、任期和命令。节点将相同的已提交命令按顺序应用,状态机才能得到相同状态。
所以,状态机逻辑应符合相应确定性要求。不能让每个节点在命令里自行读取不同随机结果,再期待业务状态自然一致。etcd-io/raft 的实现说明也强调确定性,并说明网络和磁盘 IO 由使用者配合完成。
本篇依据 Raft 原论文解释基础固定成员集群,不把成员变更、快照和实现扩展混成一套简化流程。
term 和角色,先解决当前谁来组织写入
正常情况下,Leader 通过 AppendEntries 等联系让 Follower 知道其存在。
Follower 在相应选举等待期内没有取得有效联系,可以增加 term,转为 Candidate,给自己投票并请求其他节点支持。每个节点同一任期的投票受到限制,相关状态需要持久保存。
Candidate 拿到多数派选票,才成为这个任期的 Leader。随机化选举等待时间,帮助减少多个候选持续同时发起而分票的情况;它不是保证每一次都没有竞争。
term 是单调推进的任期标识,不是机器墙上时钟。节点发现更高任期时,需要按协议更新状态,原 Leader 也不能只靠自己“觉得还活着”继续保有旧权力。
为什么投票不是谁最先来就投谁?
投票还需要检查候选日志是否足够新。
Raft 比较末条日志的任期;相同再比较末条位置。不能只数日志总条数,也不能因为 Candidate term 大,就完全不看它有没有足够日志。
这个限制帮助已提交信息在后续 Leader 中保留下来。否则,某个缺少关键记录的节点当选后,可能把已经对外承诺的修改抹掉。
所以,选举不是业务层挑一台负载最低机器当主,而是包含日志安全约束的协议。

五个节点,怎样完成当前任期的一条提交?
假设 Leader L 在当前任期新增一条日志 N,并安全记录在本地。
它向其他节点复制。若 F1、F2 也完成相应复制确认,L、F1、F2 一共三个,形成五节点的多数派;F3、F4 此刻较慢,不要求这一次先等齐五个。
在满足协议条件后,Leader 推进提交位置,按顺序应用,再返回对应处理结果。Follower 从后续协议消息得知提交进度,继续应用。
这个例子里的三份是 L、F1、F2,包含 Leader 自己。如果只收到一个 Follower 的确认,就只有两份,还不够。
复制、提交、应用是不同阶段。 保存了一条尚未提交的日志,不等于已经可以向业务宣布稳定成功;知道它已提交,也不代表每个 Follower 此刻都已经应用完成。
旧任期日志,为什么不能只照着三份计数?
新 Leader 可能携带旧任期的未提交日志。它不能仅凭“现在似乎复制到多数派”,就按当前任期新日志的方式直接推进提交。
基础 Raft 的规则是通过当前任期的日志满足多数派条件来推进提交,由此间接提交之前的前缀。原论文专门展示了旧任期直接计数可能出问题的情况。
可以把它记成:先让当前任期的一条日志满足提交条件,之前的前缀才随之确认。只背“多数派就提交”,就漏掉了任期这个前提。
实现常会借助当选后当前任期的日志安排建立这个条件,但具体是否使用 no-op、怎样组织,要看库和实现,不当成业务开发者必须手写的固定代码。

网络分区后,旧 Leader 并没有超能力
五节点分成三与二。拥有有效多数派并能维持协议进展的一侧,有机会选出 Leader、继续提交;两节点一侧无法单独组成多数派,不应继续安全提交新日志。
旧 Leader 即使还在运行,也不能仅凭自己保存成功就突破这个约束。安全性不依赖大家同时知道网络已经断开。
但“三节点一侧”也不是任何网络抖动下都必然立刻可用。选举和进展仍需要适当的通信与时序条件。etcd 官方 FAQ列出了集群多数派与故障容忍关系,五个成员的多数派是三个。

日志一致,不等于整个接口语义自动完成
Leader 已提交修改,但响应没到客户端。客户端重试,可能再次产生一条命令,因此需要请求身份和状态机层面的去重。
读取也要确认结果的最新性,不能只向任意可能落后的 Follower 查询,就宣布线性一致。具体读协议、租约假设和提交应用位置需要配套实现。
Raft 作者官网整理了论文、实现与相关说明。工程中通常使用经过验证的库。自己写几个数组和多数计数函数,可以演示日志如何复制,却还没有处理持久化、崩溃恢复和各种消息交错,不能当成完整的共识实现。
面试官继续追问
三节点集群能容忍两台故障继续写吗?
不能。多数派需要两台,只剩一台就不能完成新的安全提交。能否恢复已有数据是另一问题。
已提交,是否意味着所有节点已复制完成?
不意味着。基础规则依赖符合条件的多数派,落后节点可以继续追赶;不要混成全员确认。
同一任期可以有两个都取得多数派的 Leader 吗?
基础协议通过同任期投票限制和多数派交集防止这种结果。不同任期旧节点仍可能短时认为自己是 Leader,不能把节点的自我认识等同于有效提交权。
面试速记卡
- 目标:复制有序日志,已提交命令按顺序推进状态机。
- 选举:任期、同任期投票限制、日志新旧与多数派共同约束。
- 多数派:五个需要三个,包含 Leader 自己。
- 提交:当前任期规则不能省略,复制、提交、应用分别看。
- 边界:失去多数派不继续安全提交;重试去重和一致读还需配套。
公司面试真题
真题根据求职者公开面经整理,题意经过概括,非逐字原话或公司官方题库;本文为 Sunday 的独立解析。
美团 · 后端(榛果民宿) · 原帖未明确批次
Raft 协议怎样工作?(题意整理)
美团offer call还愿 ↗
历史面经;原帖编辑于 2019-09-18