raft
原理
参考:raft 一致性算法 动画演示
数据一致性
- 通常来说,我们的服务节点数量为3、5、7奇数
- 节点会有3个状态:Follower(从)、Candidate(候选人)、Leader(主)
- 一开始,所有节点都是Follower状态
- 然后Follower节点没有收到Leader发来的心跳,那么自己就会升级为Candidate
- Candidate节点会去询问其他节点 自己是否可以升级为Leader
- 其他节点收到后会回复投票结果
- 当Candidate收到大多数投票,就会升级为Leader
- Leader就会负责接收数据
- 每个变化都会被记录到节点日志中,如果日志未提交完成则数据不会被记录
- 假设客户端发送一个SET X
- Leader会记录日志:SET X
- Leader将数据复制给Followers,Followers会记录日志:SET X
- Leader等待大多数节点写入条目后,Leader才会真正写入数据X
- 然后Leader会告诉Followers条目已经提交,Followers也会真正写入数据X
- 这样集群的数据一致性就得到了保证
Leader选举
- raft算法有2个timeout来控制选举:election timeout和Append Entries timeout
- election timeout是决定Follower变成Candidate的,是150ms~300ms的随机值
- 当一个Follower的election timeout超时后就会进入投票阶段,然后发送投票请求给其他节点
- 如果其他节点不在Candidate阶段,那他就会同意投票,然后重置election timeout
- Candidate收到大多数的投票,就会成为Leader
- Leader按照指定时间间隔向其他节点发送Append Entries消息
- Followers会回复每个Append Entries消息,会重置election timeout
- 这个状态就会一直保持,直到Followers没有继续收到Append Entries,election timeout超时后又会成为Candidate
停止Leader
- Leader“挂掉”后,Followers就收不到Append Entries消息
- Followers等待election timeout后,会成为Candidate发起投票
- Candidate收到大多数的投票,就会成为Leader
- 现在状况是:原来的Followers(Follower + Leader)会在term1,之前挂掉的Leader还是在term2
- 如果原来的Followers刚好同时变成Candidate,无法获取大多数投票,那就会进行下一轮的选举
- 如果原来的Leader恢复了,他在term1发现现在term2更高级,就会以Follower的角色加入
日志复制
- Leader想要发生log给Followers也是通过Append Entries消息,和心跳信息一起发送给Followers
- Leader接收到数据后,自己记录log,然后将log随Append Entries消息发送给Followers
- Followers回复自己记录log
- Leader收到回复后,会同时告诉客户端、Followers,Leader将数据记录下来,Followers也会将数据记录下来
脑裂情况
- 如果集群出现了脑裂,例如在5节点的情况,出现了3节点+2节点的term (2节点一般无法选主,我们考虑双主的情况,就是3节点重新选主了)
- 客户端会向主节点发送数据,3节点和2节点的term都会接收部分数据,因为每个term都有Leader
- 但是2节点的term无法获取大多数的Append Entries,所以数据不会被实际写入
- 当集群状态恢复后,3节点的term比较大,那么2节点term之前记录的log将会被丢弃,从而同步3节点的数据