最近工作需要接触一些Raft 相关的东西,下面简单整理几点:

Raft内部相关接口

有自己的事物日志管理接口:支持append/get/ truncate 等操作;

有独立的日志同步模块:Replicator 逐一回探确定从和主日志开始分叉的位置,然后从主上拉取Follower 节点缺少的日志条目,同步给Follower,通常这是独立的线程做的事情;

Raft内部可能有Cache功能,只有当待写的日志条目内容超过一定长度的时候,再会真正下发落盘;

同步日志的时候,Raft内部会检查index ID是否和目的节点的相匹配:预期应该保证 follower当前的index id + 1 和append过来的 LOG index ID 相等;

复制组创建流程

1.主控节点随机找一个存储节点创建一个复制组的副本;

2.成功之后检查复制组成员(副本)的数量是否达到复制组约定的成员的数量;

3.如果没有达到,主控节点继续 随机找一个存储节点创建一个复制组成员;如果有达到,到步骤 1 (向主控节点 返回成功)

  1. 如果上面节点副本创建成功,向主控节点返回副本创建成功,主控节点接着向第一个副本发添加复制组成员的请求, 以便把新创建的副本添加到复制组;

  2. 继续步骤2

常见问题

  1. 解析事物日志失败

  2. 向复制组添加成员失败

  3. 复制组的 Leader 里有Follower, 但是Follower 里的成员里没有Leader

针对问题1: 需要检查load 出的Raft 日志是否和append 的相一致;
针对问题2、3: 通常是由于Leader 没有把配置变更相关的日志同步给Follower,这里可能是Leader读之前它存下来的配置变更的日志出错了,也可能是到了Follower节点但被Raft 检查index等信息失败从而被内部请求拒绝了。