https://zhuanlan.zhihu.com/p/130974371
Raft协议动画 http://thesecretlivesofdata.com/raft/
以我个人的理解来阐述一下Raft协议:
首先,Raft协议是一个单主协议,即写操作必须经过leader,再由leader将该消息同步至各follower
那么首先就讲一下选举过程:
- 如果一个follower在一个随机时间内(150-300ms)没有收到来自leader的heart beat,则其成为一个candidate参与到选举中,并将自己的term值加一
- 然后该candidate投自己一票,然后要求集群中的其他节点给它投票
- 如果收到集群内半数的投票,那么它就正式成为一个leader
选举完毕后,就进入正常同步过程:
- Client向leader发送写请求指令,leader将该请求写入日志(但没提交)
- leader去通知其他follower,
- follower收到通知后也将该请求写入日志(但没提交),并回复leader
- 如果 leader收到半数节点的回复,则提交之前没提交的日志,并通知其他follower也提交日志
- 其他follower收到后提交之前没提交的日志
那么有人可能就要问了,为什么半数同意就能达到最终一致性呢,其他小部分没收到通知的follower如何保证与其他节点的数据一致呢?
那么就考虑一下存在网络分区的情况:
- 如果原 leader所处的分区节点数超过半数,那么其他分区肯定不能选举出新leader。导致的结果就是,该leader所处分区的日志都能正常提交,其他分区的日志仅仅被记录而不能提交。这时如果连接恢复正常,那么其他分区的节点根据日志的id,将其日志同步至与正常节点一致的状态后再重新进入正常同步阶段。
- 如果原 leader所处的分区节点数没超过半数,那么超过半数节点的分区(如存在)则会选举出一个新leader,且该leader的term大于原leader。导致的结果就是新leader所处分区的日志都能正常提交,其他分区的日志仅仅被记录而不能提交。这时如果连接恢复正常,其他分区的节点发现正常的节点的term大于它的term,那么它就知道已经选举产生了新的leader,那么它就会将原term中未提交的日志抛弃,而更新至与新term日志一致的状态,从而达到最终一致性。