raft 协议实现原理

186 阅读4分钟

1 raft 核心框架

(1)传承自 multi-paxos 算法,维持一主多从的架构,整个集群有一个唯一的 leader,作为写操作的入口,这样大大降低了复杂度,具体保证有唯一的 leader,在 leader 选举机制篇中作展开.

(2)遵循多数派准则,只要一个集群中还有超过一半的节点保持健康的状态,整个集群就能提供可靠和稳定的服务

(3)两阶段提交机制,写操作从 leader 同步到 follower 的过程,分为准备和提交两个阶段.

2 leader 选举

一主多从架构,leader 尤为重要,需要保证单一、稳定.

(1)leader 会定时向所有 follower 同步心跳,告知自己仍然存活的信息

(2)每个 follower 会注册一个大于 leader 心跳间隔的超时时间,当超过时长没有收到 leader 的心跳,就会发起新一轮选举,尝试成为新一任 leader

(3)不同 follower 设置的发起选举的超时阈值不完全相同,会加上一个随机扰动,避免频繁引起竞争

(4)选举过程同样遵循多数派准则,当一个候选人获得集群中半数以上的同意票,就成为新一任 leader.

(5)选举过程中,每个节点只会投同意票给数据比自己更新的候选人,否则直接拒绝.

(6)全局维护一个单调递增的变量,称之为任期号. 每一任新 leader 产生,任期号 + 1.

3 数据同步

(1)leader 是唯一的写操作入口,需要把数据同步给集群中的 follower.

(2)数据同步过程分为两个阶段,第一阶段是 leader 生成写操作的日志,并且把这个操作同步给所有的 follower,让其也生成写操作日志;当集群中达到半数以上的节点都生成写操作日志,并且给了 leader 肯定的回复以后,说明这条写操作成功了,leader 可以真正执行提交动作,并且向所有 follower 也同步这个提交的动作.

(3)follower 在接受 leader 同步操作日志请求时,会对其进行判断,只有在其上一条写操作日志的和自己的上一条写操作日志完全匹配上的时候,才会生成写操作日志,并作肯定地答复;

(4)除了任期以外,还会生成一个全局递增的写操作日志id,通过任期 id + 日志 id 可以定位到一条唯一的操作日志.

(5)同步写操作日志的时候,follower 都会回复当前的任期. 如果 follower 的任期滞后,会作更新. 如果 follower 的任期领先于 leader,也会将其回复,leader 收到后会更新任期,并主动降级成为 follower

(6)同步写操作日志的时候,follower 发现自己的任期和 leader 相同,但是自己的操作日志 id 领先于 leader,则会将超前部分的日志全部丢弃,回到和 leader 统一水平线开始同步日志.

(7)同步写操作的时候,follower 发现自己上一条写操作日志落后于 leader 的上一条写操作日志,则不会回复肯定的答复,而是会要求 leader 把之前的操作日志同步过来,让自身先作补齐;

(8)每一个leader 当选后,只能对新任期内得到半数确认的日志做提交动作,但不能对老任期内尚未提交但得到半数确认的日志作提交,只有在新任期内有着一笔新的日志提交时,才能连带着对老任期内的日志进行提交.

4 如何读取数据 策略其实包括两种: (1)读请求也通过和 leader 的交互完成. I 假如一次读请求发给了 follower,follower 会知道自己的 leader 的身份,从而将其转发给 leader; II 由于极端情况存在网络分区,可能有任期滞后的脑裂 leader 存在而不自知. 因此一个 leader 在完成一个读请求的响应前,会给集群内的所有 follower 发一次心跳,当得到半数以上的响应,认同其合法 leader 身份时,才会进行响应.

(2)读请求向集群中全量节点发起,只要获得半数以上的节点的响应,取其中最新版本的数据就是与 leader 一致的.