前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库Raft 选举安全性 多数派投票
分布分布式系统一致性与容错

Raft 选主如何保证同一任期只有一个 Leader?

Raft 通过任期递增和每节点每任期一票的多数派投票约束,保证同一任期最多产生一个 Leader。

前端进阶之旅 · 一题精讲更新于 2026.09.05
分布式系统#一致性与容错
先看核心答案
理解线索

任期与投票约束

  1. 任期号每次选举递增,标识逻辑时间
  2. 一票制每节点对每个任期只投票一次
  3. 多数派获得超过半数节点投票才当选

即使节点重启或网络分区,只要多数派生效,就不可能选出两个 Leader。

核心回答

先记住这个答案

每个任期都有唯一编号,候选人发起选举时任期加一,节点对每个任期只投一票,只有获得多数派投票的候选人才能成为 Leader。多数派之间必有交集,因此同一任期不可能有两个 Leader 都获得多数票。

  • 任期是单调递增的逻辑时钟。
  • 每个节点每任期只能投一票。
  • 多数派必有交集,所以不会双主。

任期与投票如何锁死唯一性

Raft 将时间划分为任意长度的任期(term),每个任期有唯一整数编号。节点启动时从持久化状态读取当前任期,候选人发起选举时先自增任期号,节点收到请求后会更新自己的任期。任期作为逻辑时钟,让过期消息能被识别并拒绝,避免旧 Leader 或旧候选人干扰当前选举。

每个节点对同一任期只能投一票,记录在持久化的 votedFor 字段中。候选人获得严格多数(N/2+1)的投票即成为 Leader。多数派之间必然有交集,因为两个多数派至少共享一个节点,而该节点不可能同时投票给两个候选人,所以同一任期不可能产生两个 Leader。

五节点集群的分区选举场景

假设一个五节点集群,节点 A、B、C 在一侧,D、E 在另一侧,分区发生。A 的选举超时触发,任期从 1 变为 2,向可达的 B、C 请求投票。B、C 还没有收到更高任期,各自投给 A,这样 A 获得三票(自己、B、C),达到多数,成为分区一侧的 Leader。

D、E 无法联系 A 组,它们会不断重试选举,任期递增到 3、4……但由于只有两个节点,永远无法达到多数。集群在少数派一侧无法选出 Leader,所以不会出现脑裂。即使 D 在任期内得到 E 的选票,也仅有 2 票,不满足 3/5 的多数。

选举安全性依赖的边界条件

如果节点时钟或网络导致任期跳跃,比如一个节点因消息延迟收到更高任期,它会更新自己的任期并拒绝旧的候选人请求。但任期号本身不受时钟影响,只靠递增计数器,所以不存在时钟漂移问题。真正危险的是节点持久化存储损坏,导致 votedFor 丢失,可能在同一任期投出两票,但 Raft 要求持久化存储必须可靠。

另一个边界是“旧日志”候选人:如果某个候选人日志落后,但它仍可能当选,导致新 Leader 没有全部已提交日志。Raft 通过选举限制(候选人必须包含所有已提交日志)来解决,而不是用投票机制本身。因此,投票机制只能保证唯一 Leader,不保证日志完整,必须配合选举限制。

回答前,多想一步

容易答错的地方

认为任期相同也会有两个 Leader
有说法认为网络分区会造成双主,但 Raft 要求多数派投票,分区后少数派永远无法获得多数选票,所以不可能产生第二个 Leader。双主场景通常来自未正确实现多数派或允许旧 Leader 存留。
把 PreVote 当成选举安全的一部分
PreVote 是为了解决网络分区恢复时节点频繁打断选举的问题,它不改变投票规则,只增加一个预投票阶段。安全性仍然依赖任期和多数派,PreVote 只是优化可用性。
试着用自己的话回答

面试官还会怎么问?

投票时如何防止节点对同一候选人重复投票?

每个节点持久化 votedFor 记录当前任期已经投给了谁,如果收到同一任期的重复投票请求,且 votedFor 不是当前候选人,则拒绝;如果候选人相同,直接授予已经承诺的票。

如果两个候选人同时获得相同票数怎么办?

Raft 通过随机选举超时来减少平局概率。如果票数相同(例如各得一半),没有多数派,选举失败,所有节点超时后重新发起选举,任期递增,继续竞争。

网络分区恢复后,旧 Leader 如何处理?

旧 Leader(例如 A)收到更高任期的消息后,会发现自己任期落后,立即转为 Follower,并更新任期。它之前接受的未提交日志会被回滚,所有写入以新 Leader 为准。

从一道题,走向一组知识

把知识连起来

一致性与容错

Raft 的日志复制流程中 committed 是什么意思?

同属「一致性与容错」专题,接着看 Raft 日志复制 committed 多数派 在具体场景中的处理方式。

一致性与容错

Raft 的 PreVote 机制解决什么问题?

同属「一致性与容错」专题,接着看 Raft PreVote 网络隔离 任期膨胀 在具体场景中的处理方式。

参考资料

  • etcd versus other key-value stores

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 任期与投票如何锁死唯一性
  3. 五节点集群的分区选举场景
  4. 选举安全性依赖的边界条件
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑