6.3 转移 Leader

流程详解

流程概览

  1. 用户调用 transfer_leadership_to 接口转移 Leader

  2. 若当前 Leader 正在转移或有配置变更正在进行中,则返回 EBUSY

  3. Leader 将自身状态设为 Transferring,此时所有的 apply 会报错,Leader 停止写入,无新增日志

  4. 判断目标节点日志是否和当前 Leader 一样多:

    • 4.1 如果是的话,向目标节点发送 TimeoutNow 请求开始重新选举

    • 4.2 否则,继续在后台向 Follower 同步日志,每成功同步一批日志,就重复步骤 4

  5. 调用用户状态机的 on_leader_stop

  6. 启动转移超时定时器;该步骤后,transfer_leadership_to 接口返回成功,但变更仍在继续

  7. 节点收到 TimeoutNow 请求后,并行进行以下 2 件事:

    • 7.1 设置 TimeoutNow 响应中的 term 为自身 term 加一,并发送响应

    • 7.2 立马变为 Candidate 并自增 term 进行选举(跳过 PreVote 阶段)

  8. Leader 收到 TimeoutNow 响应后,发现目标节点的 term 比自身大,则开始 step_down 成 Follower

  9. 如果在 election_timeout_ms 时间内 Leader 没有 step_down,则取消迁移操作:

    • 调用状态机的 on_leader_start 继续领导当前任期,此时 Leader 的 term 并未改变

    • 将自身状态变为 Leader,并开始重新接受写入请求

相关 RPC

相关接口

阶段一:开始转移 Leader

transfer_leadership_to

用户调用 transfer_leadership_to 开始转移 Leader,其流程见以下注释:

判断差距

ReplicatorGroup::transfer_leadership_to 会在 ReplicatorGroup 找到目标节点的 Replicator,然后调用其 _transfer_leadership 函数。

_transfer_leadership 中主要判断目标节点的日志是否和当前 Leader 一样多:

  • 如果是的话,直接进入阶段三发送 TimeoutNow 请求进行重新选举

  • 否则,保存 lastLogIndextimeoutNowIndex,并进入阶段二继续同步日志

停止写入

阶段二:同步日志

Replicator 的作用就是不断调用 _send_entries 同步日志,直至 Follower 同步了 Leader 的全部日志才在后台等待,详见<4.1 复制流程>

同步日志

重判差距

每当收到日志复制的 AppendEntries 响应,都会回调 _on_rpc_returned

阶段三:重新选举

发送请求

Leader 调用 _send_timeout_now 向目标节点发送 TimeoutNow 请求:

处理请求

Follower 收到 TimeoutNow 请求后,会调用 handle_timeout_now_request 处理请求,具体流程见以下注释:

收到响应

Leader 在收到 TimeoutNow 响应后,会调用 _on_timeout_now_returned 进行 step_down,并在 step_down 函数中移除转移超时定时器:

其他:转移超时

如果在 election_timeout_ms 时间内 Leader 没有 step_down,则转移超时定时器就会超时,调用 on_transfer_timeout 进行处理:

Last updated