raft分布式一致性算法

155 阅读3分钟

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节点的数据