为什么三台机器就能选出一个“带头大哥“?——Raft 一致性算法,一次讲透

你存进数据库的每一笔订单,其实都躺在不止一台机器上。那问题来了:其中一台突然宕机,剩下几台手里各有一份数据,到底听谁的?凭什么保证所有副本最后长得一模一样?

这就是分布式一致性 要回答的问题。而 Raft,是今天最流行的那份答案之一------etcd、TiDB、Kafka 的新一代控制器,底层都在用它。它的设计初衷特别朴素:让一致性这件事,普通人也能看懂、能推演。


一、为什么不能简单"少数服从多数"就完事

直觉上,让所有机器投票,过半同意就执行,不就行了?没那么简单,因为有三件事同时捣乱:

  • 消息可能乱序、重复、丢失;
  • 机器可能随时宕机又随时复活;
  • 网络分区时,一半机器互相连不上,却各自为政。

在这种环境下,"多数"也得有个明确的裁决者 来组织投票、拍板执行,否则人人都是裁判,最终必然各写各的。Raft 的做法很直接:先选出一个 Leader(领导者),所有写操作都经由它统一排序,其他节点只负责跟从和备份。

把"多个决策者"收敛成"一个",一致性就从"怎么达成共识"退化成了"怎么选对人 + 怎么把命令同步过去"。这步收敛,是 Raft 好懂的根源。


二、三个角色,一个任期

Raft 里每个节点在任意时刻处于三种角色之一:

  • Leader:唯一的带头大哥,负责接收客户端请求、排序、复制日志;
  • Follower:小弟,只响应 Leader 和 Candidate,自己不主动发号施令;
  • Candidate:候选人,想当 Leader 时短暂进入的角色。

切换角色的时钟是任期(Term) ,一个单调递增的整数。每开启一轮选举,任期 +1。任期有两个作用:一是标志"时代" ------任期号更大的日志更新,冲突时谁任期大谁说了算;二是防止脑裂------两个 Leader 不可能在同一个任期里合法共存,因为当选者必须拿到"过半"的票。


三、领导者选举:靠"心跳 + 随机超时"选人

一切平静时,Leader 周期性地给 Follower 发心跳(其实就是一条空的日志复制请求),意思是"我还活着,你们别闹"。

如果 Follower 一段时间没收到心跳,就会怀疑"大哥是不是没了",于是把自己的任期 +1,变成 Candidate,发起选举,先投自己一票,再向其他节点拉票:

  • 拿到过半(N/2+1)的票 → 当选 Leader;
  • 期间收到"任期更大的领导者"的消息 → 乖乖退回 Follower;
  • 票数没够,且选举超时 → 任期再 +1,重新开选。

那个"随机超时"是关键细节:每个节点等待心跳的时长带点随机抖动,避免所有节点同时醒来、同时参选、把票打散谁都选不上。这个小小的随机数,解决了分布式系统里最经典的一类"活锁"。

为什么一定要过半 (Quorum)而不是全体一致?因为只要系统里还有超过半数节点活着,就最多只能有一个 Candidate 拿到过半票------过半是保证"任一时刻至多一个 Leader"的数学底线。而允许少数节点宕机,则让系统在损失不到一半机器时仍能继续服务。


四、日志复制:大哥先记,小弟照抄

Leader 接到一条客户端命令,做三件事:

  1. 先把命令作为一条新日志条目追加到自己日志末尾(未提交);
  2. 把这条日志发给所有 Follower,等它们各自追加;
  3. 一旦过半节点都确认复制成功,Leader 就**提交(commit)**这条日志,并把它应用到状态机(真正执行),再通知 Follower 也提交。

这个"过半确认再提交"的机制,保证了哪怕 Leader 提交后立刻宕机,新选出的 Leader 手里必然也持有这条已提交的日志------因为新 Leader 也得拿到过半票,而这两组"过半"节点必然有交集。

于是,日志就成了一份有序、一致、可回放的记录。每个节点的状态机按同样的顺序执行同样的命令,副本自然长得一模一样。


五、为什么说它"好懂"这件事本身就很值钱

Raft 之前的 Paxos,正确性没问题,但极其难懂------连提出者 Lesie Lamport 都开玩笑说"没人理解 Paxos,甚至包括我"。Raft 的作者 Diego Ongaro 在设计时立了个死规矩:任何一个能看懂它的读者,都应该能把整个算法完整地推演一遍、讲给别人听。

为了这份"可理解性",Raft 做了很多减法:把一致性拆成"选主、日志复制、安全"三个正交子问题;用任期把时序说清楚;用过半把"至多一个 Leader"变成显然。它不是靠更复杂的机制赢的,是靠把复杂的问题拆到人脑能装下赢的。

这其实给每个做系统的人提了个醒:能被人理解,本身就是一种工程价值。 一份没人敢动的代码、一个没人敢改的协议,再正确也会在维护中慢慢腐烂。


分布式一致性不在 408 统考大纲的直接考查范围内,属于进阶/延伸 内容,但它和操作系统、数据库里的"并发、事务、复制"一脉相承。想从根上补这些底子的,可以先看我的这两篇:为什么会有脏读、幻读(事务隔离本质) 和 为什么系统要加一层消息队列?------解耦、削峰、异步的本质,一次讲透。

相关推荐
本人手速666+2 小时前
企微开发API如何设计客户冻结状态?WeComApi 在删除、投诉和异常客户场景中的自动化边界
运维·分布式·自动化·企业微信·企微外部群开发·wecomapi·企业微信二次开发
灯澜忆梦4 小时前
【RabbitMQ #4】 | Work 任务模型
分布式·rabbitmq
程序猿乐锅4 小时前
【黑马点评 | 第七篇】Redis 分布式锁的两种实现
java·数据库·redis·分布式·spring·缓存
sweet丶4 小时前
iOS 为什么没有内存交换分区(swap)
操作系统
千里码aicood6 小时前
基于Hadoop的机票价格波动分析系统的设计与实现
大数据·hadoop·分布式
我爱cope6 天前
【操作系统 | 计算机硬件:CPU、内存与 I/O 如何支撑操作系统?】
学习·操作系统
Thomas.Sir6 天前
第21课:PyTorch|GPU多卡训练与分布式训练基础【让多卡并行成为你的加速引擎】
人工智能·pytorch·分布式
Cicada1286 天前
库存消息消费的正确性设计——从幂等窗口到批量流水线
分布式·系统架构
NineData7 天前
NineData 与统信服务器操作系统完成兼容认证
数据库·oracle·操作系统·软件·数据库管理工具·ninedata·统信