共识问题的核心设定

Raft解决的是分布式系统中的共识问题:让一组机器即使面临节点崩溃或网络异常,也能对同一份有序日志达成完全一致。CockroachDB、支撑Kubernetes的etcd、Kafka较新的KRaft模式以及Consul,底层都依赖这一套机制。

打开网易新闻 查看精彩图片

系统在任一时刻只允许一个领导者存在,所有写入都经由它处理。领导者由其他节点通过多数票选举产生,每次选举都会递增任期编号,任期编号在出现“谁在负责”的混乱时充当裁决依据。

五个人合写一本笔记的比喻

想象五个人试图维护一本完全相同的共享笔记,但各自待在不同房间,只能靠传纸条沟通,而且任何一个人都可能随时毫无征兆地睡着。

最初的领导者选举是这样发生的:所有人一开始都只是等待领导者的消息。如果一段时间过去没有任何动静,其中一个人会失去耐心,宣布“这一轮由我负责”,并向其他四人喊话请求支持。如果五个人中至少三个人同意,这个人就成为本轮领导者。如果恰好两个人同时失去耐心并同时请求投票,选票可能被分散,导致无人获得多数——这种情况下所有人继续等待,用新一轮重新尝试。

写入流程与多数确认

领导者产生后,所有新条目都经由它写入。领导者先把新条目写进自己的笔记,再把副本发给其他四个人。只要另外四人中至少两人确认“收到,已写下”,加上领导者自己就构成五人中的多数,领导者便认定该条目已锁定——永久生效、不可撤销。只有到这一步,它才会告诉发起写入请求的人“完成,安全了”。

如果领导者在任务中途消失,情况会怎样?假设领导者写下某条目,只收到另外一个人的确认,随后在听到其他人回复之前就睡着了,也没来得及告诉其余三人发生了什么。最终其他人察觉到沉默,发起新一轮“现在谁负责”的选举。令人安心的一点是:无论谁被选为新领导者,仅凭多数派的数学性质就能保证,这个人一定已经拥有此前所有被确认锁定的条目。任何曾被承诺为“完成”的内容都不会丢失,即使做出承诺的那个房间已经陷入沉睡。

网络分区下的多数派保证

如果群体分裂成两个互相听不见的房间,三个人的一方与两个人的一方各自为政,只有拥有多数的那一方才能继续完成写入和选举。少数派无法凑齐多数确认,也就无法让任何新条目达到锁定状态。这一约束正是Raft在节点崩溃、网络分区等异常条件下依然能保证日志一致、不丢失已确认条目的基础。