关于 raft 算法 leader 选举的一点改进想法
对于 raft 算法,leader 选举算法如下:
1. 节点角色
Raft 算法中的节点有三种角色:
(1)Leader:负责处理客户端请求、管理日志复制和发送心跳。
(2)Follower:被动接受 Leader 的日志和心跳,不主动发起请求。
(3)Candidate: 在选举过程中,Follower 可以转变为 Candidate,发起选举。
2. 选举触发条件
Leader 选举通常在以下情况下触发:
(1)Leader 失效:Follower 在一定时间内(选举超时时间)没有收到 Leader 的心跳。
(2)新节点加入:新加入的节点可能触发选举。
(3)分区恢复:网络分区恢复后,可能触发选举。
3. 选举过程
选举过程分为以下几个步骤:
(1)Follower 转为 Candidate
1)当 Follower 在选举超时时间内没有收到 Leader 的心跳,它会认为 Leader 失效。
2)Follower 将自己的角色转变为 Candidate,并开始一次新的选举。
(2)Candidate 发起投票
1)Candidate 首先将自己的任期号(Term)加 1,表示新的一轮选举。
2)Candidate 向集群中的其他节点发送 RequestVote RPC,请求投票。
3)Candidate 会投票给自己。
(3)其他节点投票
1)收到 RequestVote RPC 的节点会检查以下条件:
- Candidate 的 Term 是否大于或等于自己的 Term。
- 自己是否已经投票给其他 Candidate。
- Candidate 的日志是否至少和自己一样新
2) 如果满足条件,节点会投票给 Candidate,并重置自己的选举超时时间。
(4)选举结果
1) 如果 Candidate 收到超过半数节点的投票,它将成为新的 Leader。
2) 新的 Leader 会立即向其他节点发送心跳,以阻止其他节点发起新的选举。
(5)选举失败
1)如果 Candidate 在选举超时时间内没有获得足够的投票,选举失败。
2)Candidate 会等待一段随机时间后重新发起选举(避免多个节点同时发起选举导致分裂投票)。
4. 选举超时时间
(1)为了防止多个节点同时发起选举,Raft 使用随机化的选举超时时间(通常为 150ms-300ms)。
(2)随机化超时时间可以减少选举冲突的概率。
5. 日志一致性保证
(1)在选举过程中,Raft 通过比较日志的 Term 和 Index 来确保只有日志足够新的节点才能成为 Leader。
(2)这保证了 Leader 的日志包含所有已提交的日志条目,从而确保一致性。
6. 选举优化
(1)Pre-Vote 机制:在正式发起选举前,Candidate 可以先发起 Pre-Vote 请求,确认自己是否有机会赢得选举,避免不必要的 Term 增加。
(2)Leader 转移:在某些情况下,Leader 可以主动将领导权转移给其他节点,避免频繁选举。
下面是改动内容:
选举过程:
选举过程分为以下几个步骤:
(1) Follower 转为 Candidate (这个步骤没有改变)
1) 当 Follower 在选举超时时间内没有收到 Leader 的心跳,它会认为 Leader 失效。
2)Follower 将自己的角色转变为 Candidate,并开始一次新的选举。
(2) Candidate 发起投票 (这个步骤发生改变)
1) Candidate 首先将自己的任期号(Term)加 1,同时 Candidate 生成一个 int64 的随机数 randPriority,表示新的一轮选举。
2) Candidate 向集群中的其他节点发送 RequestVote RPC(这个 RPC 请求中会携带这个随机数 randPriority),请求投票。
3) Candidate 会投票给自己。
(3) 其他节点投票
1)收到 RequestVote RPC 的节点会检查以下条件:
- Candidate 的 Term 是否大于或等于自己的 Term。
- 自己是否已经投票给其他 Candidate。
- Candidate 的日志是否至少和自己一样新
2)如果满足条件,节点会投票给 Candidate,并重置自己的选举超时时间。
3)收到 RequestVote RPC 的节点会记录下满足如下条件的 Candidate 节点中的最大值 maxNodePriority(先日志的 offset,后Term,最后随机数 randPriority):
- Candidate 的 Term 是否大于或等于自己的 Term。
- Candidate 的日志 offset 是否至少和自己一样新
4) 节点如果拒绝投票给这个 Candidate(不满足条件,或者已经投票给其他的节点),将会返回一条消息,告诉这个 Candidate。
(4)投票结果(收到拒绝投票)
1) 如果 Candidate 收到拒绝投票的消息,而且满足许下的条件
- 如果这个消息告诉投票节点,因为日志比较旧的原因,
- 如果这个消息告诉投票节点,该节点已经投票给了其他节点,那么这个 Candidate 节点会把其他节点记录下来形成一个其他节点列表(VoteOtherList),一直到这个节点收到的被拒绝的节点数超过半数(意味着这个节点按照 raft 的标准算法已经不可能被选上,这种情况下,需要自救),那么,如果这个 candidate 节点的 nodePriority 比这个节点记录的 maxNodePriority 小,或者比 VoteOtherList 中的最大的 nodePriority 小
那么这个节点会发起特定节点重新投票的流程。
2) 特定节点重新投票的流程
- 主动放弃这一轮的 Candidate 身份
- 给所有投票给自己的节点发送让其重新投票的消息(发送的消息中包含这个节点记录最大 nodePriority 的 Candidate 节点,从 VoteOtherList 和 maxNodePriority 中获取最大值)
- 收到这个消息的节点,会对比消息中的 maxNodePriority 和本地记录的 maxNodePriority 中的较大值,然后发送投票给这个节点的消息
特定节点重新投票的流程是为了让票尽可能得汇聚到拥有最大 nodePriority 的节点上面,从而完成选举过程。
(5)投票结果 (收到同意投票)
1)如果 Candidate 收到超过半数节点的投票,它将成为新的 Leader。
2)新的 Leader 会立即向其他节点发送心跳,以阻止其他节点发起新的选举。
(6) 选举失败
1)如果 Candidate 在选举超时时间内没有获得足够的投票,选举失败
2) Candidate 会等待一段随机时间后重新发起选举
Leader 选举示例:
假设有一个 5 节点的集群(A、B、C、D、E):
raft 一次选举就可以成功的情况:
1. 初始状态下,A 是 Leader,其他节点是 Follower。
2. A 失效后,B 和 C 的选举超时时间到期,转为 Candidate。
3. B 和 C 分别发起选举,向其他节点发送 RequestVote RPC。
4. 假设 B 的日志比 C 新,D 和 E 投票给 B。
5. B 获得 3 票(包括自己),成为新的 Leader。
raft 一次选举不成功的情况:
1. 初始状态下,A 是 leader,其他节点是 Follower。
2. A 失效后,B,C,D,E 的选举超过时间到期,转为 Candidate。
3. B,C,D,E 分别发起选举,向其他节点发送 RequestVote RPC。同时 B,C,D,E 分别获得随机数 100, 90, 80, 70。
4. 假设 B,C,D,E 分别获得 1 票,由于 C,D,E 都收到了三票被拒绝的消息(超过半数),所以这三个节点都会声称放弃这一轮的candiate身份,然后向自己发送消息(这三个都向自己投票),告诉转投票给 B 节点。
5. B 节点获取了 4 票,超过多数,完成选举过程。
raft 另外一种情况:
1. 初始状态下,A 是 leader,其他节点是 Follower。
2. A 失效后,B 和 C 的选举超时时间到期,转为 Candidate。
3. B 和 C 分别发起选举,向其他节点发送 RequestVote RPC,同时 B 和 C 的随机数分别为 900, 1000。
4. 假设 B 和 C 的日志 offset 相同,分别获得了 D 和 E 的投票,那么这里可以考虑使用一种启发式想法,我们认为 A 节点没办法投票,那么 B 和 C 都认为在现有的 raft 算法逻辑下,都不会成为主节点,由于 C 节点 offset 大,C 节点不会发起特定节点的重新投票。而 B 节点会放弃这一轮的 candidate 身份,同时告诉投给它的 B 节点和 D 节点,让这两个节点转投 C 节点。
5. C 节点获取了 4 票,超过多数,完成了选举过程。
关于这个想法的正确性说明:
在任何时刻,每个节点只会投一个 Candidate,那么任何时刻,就最多有一个节点拥有超过半数的节点投票。
效率说明:
在 raft 正常 work 的状态,新的改动不会有什么影响,而在 raft 算法在一次选举过程中,没办法选出一个节点作为主节点时,可能促使选出一个主节点。
欢迎就上面的想法提出各种意见或者建议,谢谢。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗