#raft # Cluster membership changes - 实现:增加两个 RPC - AddServer RPC - RemoveServer RPC ## AddServer RPC - ![450](https://img.jonahgao.com/oss/note/2025p1/raft_addserver_rpc.png) - **参数** - newServer:添加新 server 的地址 - **返回值** - status:添加成功返回 OK - leaderHint:最新的 leader 地址(如果知道的话) - **接收者实现** 1. 如果不是 leader 返回 NOT_LEADER 2. 在固定轮数内让新 server 赶上进度; - 如果新 server 在一个选举超时内没有进度更新,或者最后一轮花费的时间超过选举超时,返回 TIMEOUT; 3. 等待 log 中之前的 configuration 变成 committed 4. 追加新的 configuration entry 到 log 中(日志内容:旧配置 + 新 server),使用新配置的 majority 来完成该条日志的 commit 5. 回复 OK ## RemoveServer RPC - ![450](https://img.jonahgao.com/oss/note/2025p1/raft_removeserver_rpc.png) - **参数** - oldServer:需要删除的 server 地址 - **返回值** - status:如果删除成功返回 OK - leaderHint:同上 - **接收者实现** 1. 回复 NOT_LEADER 如果当前接收者不是 leader 2. 等待 log 中之前的 configuration 变成 committed 3. 追加 new configuration entry 到 log 中(日志内容:旧的配置),使用新配置的 majority 完成该条日志的 commit 4. 回复 OK;并且如果删除的是当前 server ,执行退出 -------- # Safety - 同一个 term 不能选出两个 leader - 如果一次性添加 / 删除多个 servers 可能会出现(分裂成两个独立的 majorities) - ![400](https://img.jonahgao.com/oss/note/2025p1/raft_joint_problem.png) - 旧:3个节点;新:添加2个新节点(4 和 5) - **single-server approach** - 一次性只能添加 / 删除 一个 server - 新旧配置的两个 majorities 总是会重叠,避免分裂成两个独立的 majorities - 因此可以直接切换到 new configuration - 当 leader 收到变更请求后,追加 new configuration ($C_{new}$) 到 log 中,并使用正常 raft 机制复制 它。 - 每个 server 上**新配置的生效时机**:当 $C_{new}$ 添加到它的 log 中时 - 即每个 server **不需要等待** $C_{new}$ entry 的 commit,**始终使用 log 中发现的最新配置即可**。 - 配置变更操作**完成的标志**:$C_{new}$ 变成 committed 后 ( 即复制到**新配置**下的 majority 中) - 此时 leader 就可以确认: $C_{new}$ servers 的 majority 已经应用了 $C_{new}$; - leader 也知道 没有应用 $C_{new}$ 的 servers 未来不会再组成 majority,而且它们也不会被选为 leader - $C_{new}$ 的提交使三件事能够继续进行: 1. leader 可以确认配置变更已经成功完成 2. 如果配置变更是删除一个 server,那么这个 server 可以 shut down 3. 可以开始处理新的配置变请求 - 在此之前,overlapped configuration changes 可以会导致出现两个 majorities - 问题:如果 leader 发生变更,新配置对应的 log 可能会被删除 - server 需要具备 **回滚** 到之前配置的能力 - 投票和日志复制需要的修改: - server 需要接受 不在当前配置内的 leader 的 AppendEntries 请求,否则新加入的 server 就无法加入到集群 - server 需要处理 不在当前配置内的 candidate 的投票请求(如果日志足够新就同意)。 - 例如 3 个节点上添加一个新节点,如果挂掉一个,新节点的 vote 是必须的 ------