为了提升服务的高可用、高性能,通常采用多节点架构。
一个节点时候,数据是一致的。多个节点的情况下,如何保证数据一致性呢?
本文介绍的RAFT协议,就是解决多节点情况下,数据一致性问题。
1.基本概念
节点有三种角色:leader, candidate, 和follower.
在Raft选举中,有两个控制选举的超时设置: 选举超时(election timeout)和心跳超时(heartbeat timeout)
选举超时是,follower等待成为candidate的时间。
心跳超时是,leader定期向follower发送心跳消息的时间。
leader节点会定期发送心跳给其他节点。其他节点收到心跳消息后,会重置选举超时时间。
选举超时的时间,随机分配在150ms到300ms之间。
所以,每个follower的选举超时时间是随机的,以免重合。
在选举超时后,follower成为candidate, 并开始新的选举周期(election term)。
每发起一次选举,选举周期(election term)自动加1。
2.选举过程
刚开始的时候,节点都是follower。
选举超时时间最先到的follwer,自动变为candidate,发起投票。它首先会给自己投一票。
接着向其他节点请求投票,其他节点回复投票。
每个节点一个选举周期之内只能投一票,它会将票投给最先请求投票的candidate。
如果candidate获得超过半数的投票,那么它就成为leader。
接着,leader定期向其他节点发送心跳消息。
如果leader节点宕机,无法发送心跳消息后,其他follower开始新的一轮选举。
3.数据更新过程
在RAFT中,数据更新操作是通过Log Replication实现。
系统中所有更新操作都要经过leader。
client向leader发送请求后,leader将消息同步给其他节点。
具体过程:
(1) leader将更新操作(append entry)同步给所有节点,是附加在心跳消息中发送的。此时是未提交状态uncommited。
(2) leader 如果收到超过半数的回复,那么它回复client OK,接着提交commit,并通知其他节点已提交,其他节点收到消息后也提交。
(2) leader如果没有收到超过半数的恢复,这个更新操作就不会提交。
通过以上步骤就完成了一次更新。
4.网络分区
如果遇到网络分区,RAFT是否仍然可用呢?
假设一个5个节点集群:A, B, C, D,E.
当时B是leader, term是1。
网络分区后,A,B一个区, C, D, E是另一个区。
C, D, E无法收到心跳消息,选举超时后,重新开始投票,term变为2, 接着选出一个新的leader C。
如果此时有更新操作发送到A, B这个分区。leader B 将更新请求发送到所有节点,只有A,B回复,不能收到超过半数的回复,所以无法提交。
而才是更新操作发送到C,D, E这个分区。leader C 将更新请求发送到所有节点,可以收到超过半数的回复,所以可以提交。
如果后面网络分区消失后,leader B发现自己的term小,就会自动退出。并从新leader C同步最新状态。
从而系统达到一致状态。
5.容灾性
因为RAFT要求任何更新操作,都要超过半数节点的回复。
如果不能达到半数,就不会提交。
所以,一个多节点的系统,容灾性如下:
2个节点,不具备容性,其中任何一个节点挂掉,系统就不可用。
3个节点,可以允许一个节点失效。
5个节点,可以允许两个节点失效。