JRaft源码剖析2-Leader选举

2023-10-01  本文已影响0人  王侦

1.term 和 logIndex

Raft 算法设计了 term 和 logIndex 两个属性,分别用于表示 Leader 节点的任期,以及集群运行期间接收到的指令对应的日志条目的 ID,这两个属性都是单调递增的。

Raft 算法要求节点在给参选节点投票时必须保证参选节点满足以下两个条件之一:

这两个条件的目的都在于保证当前参选节点本地的日志数据不能比投票节点要陈旧。

2.为什么需要预选举步骤?

JRaft 在设计层面将选举的过程拆分为预选举和正式选举两个过程,之所以这样设计是为了避免无效的选举进程递增 term 值,进而造成浪费,同时也会导致正常运行的 Leader 节点执行角色降级。

3.预选举

当启动一个 JRaft 节点时,如果初始化集群节点配置不为空,则节点会调用 NodeImpl#stepDown 方法执行角色降级操作。所谓角色降级实际上是一个宽泛的说法,因为 NodeImpl#stepDown 方法会在多种场景下被调用。而这里调用该方法的背景是一个 FOLLOWER 节点刚刚启动的时候,所以除了初始化一些本地状态之外,整个角色降级过程重点做的一件事就是启动预选举计时器 electionTimer。

NodeImpl#init
-> NodeImpl#stepDown
-> this.electionTimer.restart()
-> RepeatedTimer#restart
-> RepeatedTimer#schedule
-> RepeatedTimer#run
-> 回调 onTrigger()

在NodeImpl#init中看electionTimer的onTrigger()实现:

        this.electionTimer = new RepeatedTimer(name, this.options.getElectionTimeoutMs(),
            TIMER_FACTORY.getElectionTimer(this.options.isSharedElectionTimer(), name)) {

            @Override
            protected void onTrigger() {
                handleElectionTimeout();
            }

            @Override
            protected int adjustTimeout(final int timeoutMs) {
                return randomTimeout(timeoutMs);
            }
        };

核心是NodeImpl#handleElectionTimeout,默认随机区间为 1~2s。

NodeImpl#handleElectionTimeout

预选举的特点:

4.正式选举

触发正式选举进程,除了发生在预选举成功之后之外,主要还包括另外两个场景:

NodeImpl#electSelf

在节点成为 LEADER 角色之后会将集群配置信息作为第一条日志进行提交,还有另外一个考虑。当一个节点刚刚竞选成为 LEADER 角色时,此时该节点本地的 committedIndex 值并不一定是当前整个系统范围内最新的 committedIndex 值,这会影响线性一致性读结果的准确性,而通过提交日志操作则能够保证新的 Leader 节点的 committedIndex 被更新为集群范围内的最新值。

5.Leader 让权

Leader 节点需要定期检查自己的权威是否持续有效,即集群中过半数的 Follower 节点都能响应自己的心跳请求,如果不是则需要让权。这一过程由 stepdown 计时器 stepDownTimer 负责,由前面 NodeImpl#becomeLeader 方法的实现也可以看到在节点成为 LEADER 角色之后会启动 stepdown 计时器。

NodeImpl#handleStepDownTimeout
-> NodeImpl#checkDeadNodes如果集群中认同当前 Leader 节点的 Follower 节点数过半,则无需让权;集群中认同当前 Leader 节点的 Follower 节点数小于一半,执行让权操作
-> NodeImpl#checkDeadNodes0 会检查目标 Follower 节点与当前 Leader 节点最近一次的 RPC 请求时间戳,以此决定对应的租约是否仍然有效
-> NodeImpl#stepDown 节点以 LEADER 角色调用该方法,除了将角色切换成 FOLLOWER、初始化本地状态,以及启动预选举计时器 electionTimer 之外,在此之前还会执行如下一段逻辑:停止 stepdown 计时器、清空选票箱、向状态机调度器发布 LEADER_STOP 事件。LEADER_STOP 状态机事件会触发 FSMCaller 回调应用程序实现的 StateMachine#onLeaderStop 方法。

上一篇 下一篇

猜你喜欢

热点阅读