Raft算法理论与应用

Raft算法理论与应用

  • 引言
  • 1 原理
    • 1.1 算法过程
    • 1.2 美中不足
    • 1.3 再度升华
  • 2 应用
    • 2.1 主从备份
      • 2.1.1 数据操作算法
      • 2.1.2 节点加入/移除
      • 2.1.3 运维事项

引言

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

1 原理

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

1.1 算法过程

首先,节点加入时为follower状态。当节点超过一定时间没有收到notifyLeader消息就会调用switchToCandidate方法,切换到candidate状态。具体如下:
Raft算法理论与应用_第1张图片
然后,每个节点收到notifyLeader消息,都会做相应的处理。其处理流程如下:
Raft算法理论与应用_第2张图片
注:当一定时间间隔没有收到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、follower和candidate。leaderUnReady和leaderReady都是leader状态,前者是刚刚成为leader且正在进行数据同步、只提供对数据只读操作,后者是成为leader且数据同步完成、对数据提供读写操作;follower和candidate与原生算法一致,不作额外说明。

  • 竞选leader

Raft算法理论与应用_第3张图片
注:竞选过程与原生算法基本一致。此外,notifyLeader多了一个MinUnSyncId参数。

  • 处理心跳

Raft算法理论与应用_第4张图片
注:当一定时间没有收到newTerm>=CurrentTerm的心跳时,就会调用switchToCandidate启动竞选。特别地,对于Leader节点和非Leader节点接收到消息时的状态设置,有所不一样;Leader节点在LeaderUnReadyState状态下不提供写操作、仅提供读操作,需要待调用syncDatas同步数据完毕并切换为LeaderReadyState状态才可进行写操作。此外,对于follower节点,当主节点的最小未同步ID大于自己的最小未同步ID,说明有新数据,需要触发数据更新

  • 写入数据

Raft算法理论与应用_第5张图片
注:写入数据成功,会将同步id发给所有备份节点。若是过半返回success,就会提交写入,反之,则回滚写入。当备份节点收到新的同步id后,会写入sync文件,对应的state为未知,然后去拉取sync对应的状态。当数据状态同步完成后,需要通过updateDatas函数有序地同步数据。特别地,当主节点sendSyncDatasToAll后宕机,会造成对于该日志是否提交或撤销的状态不确定,这有一定的低概率发生,需要人工修复。

  • leader同步

Raft算法理论与应用_第6张图片
注:过半返回没有更多的syncId且fileBlockDataArr为空的blockDatas,表明数据已经到最新,就直接进入leaderReady状态、然后退出同步;否则,进行下一轮循环同步。注意在下一轮同步前,判断存在fileBlockDataArr非空的blockDatas,就必须将数据写入DB文件,并递增最小未同步的ID;此外,不存在fileBlockDataArr非空的blockDatas,但存在过半返回fileBlockDataArr为空的blockDatas,会递增最小未同步的ID(因为事务可能被回滚等原因取消)。

  • follower同步

Raft算法理论与应用_第7张图片
注:除了写入数据会发起follower的同步外,收到主节点心跳,发现有新数据也会触发follower的同步。
此外,follower节点会定期将自己的MinUnSyncId写入主节点,同时主节点也会写入。这样,当同步到各个节点的时候,每个节点可以删除小于所有节点MinUnSyncId值的所有同步记录。

2.1.2 节点加入/移除

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

  • 节点加入

Raft算法理论与应用_第8张图片
注:当节点信息写入数据库后,它会按前面的数据写入流程同步到备份节点。然后,就是请求数据下载,可以采用一页一页地将持久化的文件数据页传给新进节点。
特别地,在开始下载和完成下载,会返回一个当前主节点的最小未同步ID;然后下载完毕,新加节点会将开始下载时返回的最小未同步ID作为自己节点的最小未同步ID;最后一致同步到借点ID大于或等于下载完毕时主节点的最小未同步ID。这样做是有必要的:因为在下载过程中,已下载和未下载的文件页有可能被执行写操作。

  • 节点移除

Raft算法理论与应用_第9张图片
注:与节点加入一样,只不过移除节点只能是FollowerNode。特别地,若是移除LeaderNode,需要先停止LeaderNode的心跳,使其降为follower,然后再移除。

2.1.3 运维事项

运维需要注意:

  1. 监听follower节点长时间为UnKnown状态的记录,需要进行人工检查并修复;
  2. 每次加入节点个数必须少于一半,然后将所有节点更新到最新;
  3. 每次移除节点个数必须少于一半,然后将所有节点更新到最新;

你可能感兴趣的:(分布式基础)