前言
如果有多个机器(集群),则需要保证每个机器数据的一致性,这时候则需要分布式共识算法。Raft是实现分布式共识算法的协议,除了Raft,还有Paxos、ZAB、Gossip等。
Leader election
每个节点有三个状态,分别是Leader、Follower或Candidate
一开始的时候,所有节点都处于Follower的状态。每个结点都有一个Election Timeout(随机在150ms-300ms,可以在config中设置),如果有一个结点超时没有从Leader中获得消息,它们则会变为Candidate
Candidate会向其它结点请求投票数,在任期之内没有投票过的Follower可以投票(避免重复投票)。
若获得超过半的投票数(保证了leader的唯一性),则该Candidate会变成Leader,其它的follower的会重置计时器(不着急成为candidate)
- 若获得平票,则等待timeout并重新发起选举(因为timeout是随机数,因此平票几率少)
Leader会周期地发送Heartbeat Timeout给Followers,以重置timer,使其不会因为超时而变为Candidate(因为选举是一个耗时的操作,如果leader存活的话,则不用频繁更换leader)。Followers会返回AppendEntries的消息给Leader。
Log replication
如果集群中一个机器挂了,通过把日志复制到(广播)到其它服务器,其它的服务器都会有共识/majority,可以用于恢复日志(容错性)
- 当client给leader发送操作请求,leader都会将请求记录在该结点的日志行中,此时的数据是uncommitted状态(不会改变原来的值,机器挂掉/网络故障了该操作也不会被保存下来)
- Client对系统的操作(读、写)都要通过leader同意,若client把请求发送给follower,follower同样要把请求转发给leader
- 然后leader结点会通过next hearbeat把该请求replicates到别的follower结点中。followers发送AppendEntries请求,将数据操作写到本地日志中(uncommitted状态),ok的话,会返回一个投票。
- 若超过半数的Followers知道了操作变更,则Leader会把操作写入(AppendEntries),变为commited状态(已持久化状态),并通知其它followers将本地日志中uncommitted的日志改committed,并更新数据。返回相应给client
- 此时,整个集群的数据是一致的(consensus)
参考
- http://thesecretlivesofdata.com/
- https://www.bilibili.com/video/BV1Wy4y1K7zF/?spm_id_from=333.337.search-card.all.click&vd_source=d85f289ebf4d31920c7178bbb563a0a4
- https://raft.github.io/raft.pdf