共识算法
目的:实现分布式环境中的强一致性。
##基本概念
每个节点有三个状态:
1.Follower:从
2.Candidate:参选
3.Leader:主
和一个倒计时:Election Timeout(时间随机)在以下两种情况下会重设:
1.收到Election请求
2.收到Leader的Heartbeat
##首先选举Leader
###正常情况
当A节点的Election Timeout到期时,其状态变为Candidate。他向其他节点发送请求,当有超过半数(包括自己)的节点回复收到请求并同意(同意的标准就是自己的状态不是Candidata),A就成功当选Leader,并且记录A当选为Leader的轮数为n。
###异常情况
当A挂了,因为Heartbeat没了,Election Timeout不会再刷,就会导致B节点的Election Timeout到期。B同样经历上述流程,成功当选为第n+1轮的Leader。
此时A又恢复了,他认为自己是Leader,但是他是n轮的Leader,所以他自觉降级为Follower。
##如何确保一致性?答案:日志复制
以Leader为主,数据提交的时候,Leader写入日志,并标记为uncommit,然后发送给Follower,当收到超过半数(包括自己)的节点回复收到日志的时候,就认为此次提交成功,并将日志标记为committed,此后响应才返回给Client。
##如果部分节点失联怎么保证一致性?
用伪代码表示这个流程:
if leader is online:
if leader 可以连通超过半数节点:
return true #告诉client提交成功,在此之后失联的那一半回来以后可以继续同步这些日志。
else:
return false #告诉client提交失败,此时集群不可用。但不是一直不可用(看到没?CAP中,实现了C就不能实现A)
else: #leader已经失联了
if 失联节点超过半数:
return false #告诉client提交失败,集群已经崩了,没办法自愈了,要么等来电来网,要么赶紧跑路吧
else:#还能连接的节点超过半数
Election() #重新选举新的leader。根据上面讲到的异常情况,这时选举的轮数n会+1。当之前失联的节点恢复了(包括原来的leader)的时候,他们会自觉变成follower