分布式技术栈–Raft算法理论与应用

引言

在分布式系统中,为了满足分区容错,即当某个节点宕机、还能正常服务且数据不丢失。常常采用多节点备份,然后在多个节点选择一个主节点提供读写操作,其他节点只提供读取操作。Raft算法便是一种比较普遍的主节点竞选算法。

1 原理

算法中节点有三个状态:leader、follower和candidate。leader是节点被选为主节点状态、follower是节点作为从节点的状态、candidate是主节点失联后竞选自己为主节点状态。
每个节点都会缓存一个term值;每竞选一次都会递增一次term;每个节点只投票竞选序号大于缓存的term值的竞选请求;当节点投票竞选请求时,会将term值设置为请求中的竞选序号值;当有过半的节点投票通过,就会升级为leader节点;当leader节点向所有节点通知自己竞选成功序号的心跳时,其他节点收到后就会进入follower状态。

1.1 算法过程

首先,节点加入时为follower状态。当节点超过一定时间没有收到notifyLeader消息就会调用switchToCandidate方法,切换到candidate状态。具体如下:
在这里插入图片描述
然后,每个节点收到notifyLeader消息,都会做相应的处理。其处理流程如下:
在这里插入图片描述
注:当一定时间间隔没有收到term>=CurrentTerm的notifyLeader,就会调用switchToCandidate方法。

1.2 美中不足

当有四个节点A、B、C、D,A和B同时发起竞选节点且reqTerm值为1;其中A和B先收到A的请求,给予了A投票,而C和D先收到B的请求,给予了B投票;依次第二次、第三次。。。最后造成死循环而无法过半通过、竞选不出leader。

1.3 再度升华

为了解决美中不足的问题,在节点发起第一次请求超时后,给予节点一个随机的超时间隔。特别地,随机超时间隔所在区间不要超过某个上限。

2 应用

2.1 主从备份

2.1.1 数据操作算法

首先,在原生算法三个状态扩展为五个状态:leaderUnReady、leaderReady、followerUnReady、followerReady和candidate。leaderUnReady和leaderReady都是leader状态,前者是刚刚成为leader且正在进行数据同步、只提供对数据只读操作,后者是成为leader且数据同步完成、对数据提供读写操作;followerUnReady和followerReady都是follower状态,前者是刚刚成为follower且正在进行数据同步、只提供对数据只读操作,后者是成为follower且数据同步完成、对数据提供读写操作;candidate与原生算法一致,不作额外说明。

  • 竞选leader

在这里插入图片描述
注:竞选过程与原生算法基本一致,其中RaceTerm的递增算法是为了保证最后已提交的binLog包含在新选出的LeaderNode中。此外,Leader和Follower状态分为ready和unready两种。

  • 处理心跳

在这里插入图片描述
注:当一定时间没有收到newTerm>=CurrentTerm的心跳时,就会调用switchToCandidate启动竞选。特别地,对于Leader节点和非Leader节点接收到消息时的状态设置,有所不一样;Leader节点在LeaderUnReadyState状态下不提供写操作,需要待LeaderRecover完毕并切换为LeaderReadyState状态才可进行写操作。此外,对于follower节点,也是先进入FollowerUnReadyState后,待FollowerRecover完毕切为FollowerReadyState才能接受主节点写入同步。

  • 写入数据

在这里插入图片描述
注:一旦主节点将binLog写入成功后,就会向所有的从节点同步binLog、直到过半返回success。从节点收到binLog后,首先拉取还未同步到的binLog;所有的binLog有序执行到XA Prepare阶段;主节点在最后commitXA后,会将prepare状态的xid通知给所有的从节点,然后从节点commit不在prepareXidList中挂起的事务。特别地,需要保证不同节点生成的xid不能出现相同的情况。此外,leader除了有事务提交时会发送notifyPrepareXidList消息外,还会定时进行发送notifyPrepareXidList消息。

  • leader复位

在这里插入图片描述
注:当节点重启后,若状态为leaderUnReady或leaderReady,也会执行leaderRecover。它将所有prepare状态的binglog依次同步到所有从节点。如果success返回过半,就提交XA事务(此外,还有需要记录这些被延迟提交、没有成功返回的XA事务),然后continue循环;反之,就会持续发起recover同步。特别地,如果中途接收到冲突,就记录下来并发给运维人员。
之所以要处理冲突,需要考虑如下:

  1. 假定有编号为0到9十个节点,其中0号为主节点。其中0号成功提交了binlog序号为5的事务,且在1到9号节点也已都同步提交;
  2. 然后0号节点有序发起了binlog序号为6、7的事务,但是由于网络原因只有7、8、9号三个节点返回成功,然后0节点突然宕机。此时1到6号节点没有未提交的binglog,且最后提交的binglog序号为5;7到9号节点都有binlog序号为6、7的事务未提交;
  3. 这时,1到9号会执行主节点选举。假设,此时1到6号在一个机房、7到9号在另一个机房,然后两个机房通信出了故障,那么此时1到6号就会成功竞选一个主节点,假设为1号;当然7到9号会一直处于竞选状态;
  4. 1号节点再发起了一个序号为6的binlog,假设2到6都成功返回,那么此时1到6号节点的序号为6的binglog与7到9号节点中序号为6的binlog是不一致的。如何此时1到6的机房连接7到9的机房网络恢复,那么7到9中某个节点成功竞选成了主节点后,此时就会有不一致的数据。
  • follower复位

在这里插入图片描述
注:当节点重启后,若状态为followerUnReady,也会执行followerRecover。followerRecover将回滚与主节点不一致的XA事务、或binLogNum比主节点lastBinLogNum大的XA事务。

2.1.2 节点加入/移除

数据节点的加入/移除,可以看成也是一种对数据的写入。只是这里的数据就是节点信息表内容的添加或删除。

  • 节点加入

在这里插入图片描述
注:节点加入是向系统NodeTable中插入节点;然后启动串行化读,串行化事务隔离是为了在拉取db数据时,防止被后续事务污染,当然如果采用MVCC下的repeatable-read隔离更好。

  • 节点移除

在这里插入图片描述
注:与节点加入一样,只是在NodeTable中删除自己。

2.1.3 运维事项

运维需要注意:

  1. 每次加入节点个数必须少于一半;
  2. 每次移除节点个数必须少于一半;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值