有没有可能出现两次选举成功的间隔小于election_timeout导致lease read失效?
cangfengzhs opened this issue · 5 comments
如下case:
三节点{A, B, C}
1. A向BC请求投票
2. BC都成功给A投票
3. B选举超时,开始preVote
4. A当选为Leader (Term=1),之后开始向BC发送心跳
5. B向AC请求投票
6. C成给B投票
7. B当选为Leader(Term=2)
follower在handleRequestVoteRequest中vote成功时,并没有renew follower_lease。这种情况下follower(B)在vote成功后会立即开始新的一轮选举,导致AB两个node在很短时间内先后当选为Leader
会有这种情况发生吗?
B向C请求preVote,C会返回成功啊
在JRaft的stepdown中有更新updateLastLeaderTimestamp,保证了之后的handleElectionTimeout在尝试选举前检查lastLeaderTimestamp间隔小于选举间隔。
在Braft中起到类似作用的应该是FollowerLease,但是在step_down函数中,并没有调用_follower_lease.renew()。
是有其他机制来避免我上面说的问题吗
在JRaft的stepdown中有更新updateLastLeaderTimestamp,保证了之后的handleElectionTimeout在尝试选举前检查lastLeaderTimestamp间隔小于选举间隔。
在Braft中起到类似作用的应该是FollowerLease,但是在step_down函数中,并没有调用_follower_lease.renew()。
是有其他机制来避免我上面说的问题吗
从目前实现来看,当raft_enable_leader_lease
开启时,的确可能发生上述现象。即节点刚投票成功后,等待 leader 的心跳前,如果此时 election_timer
超时, 或者已经超时,只不过在等待锁。那么该节点可以成功发起 PrevVote
, 从而触发下一个 term 的选举, 而上一个 term 的 leader 却还在 lease有效期内。
但是在实际情况中,该问题不会导致严重的后果。因为当 leader 当选成功后,并不会立即调用 fsm->on_leader_start, 而是会先将当前最新的 configuration 复制到大多数节点(commit)后才会正式对外提供服务。 所以,即使发生上述情况,老term的 leader 会无法完成第一个日志的复制,并且发现已经有新的leader产生,从而转为follwer。
综上上述现象会发生,但是仅发生在老 term 的 leader 当选以及第一次日志复制过程中,而该过程并不会对外提供服务,所以是安全的。
对于该问题,论文 $5.2 节描述如下:
server remains in follower state as long as it receives valid RPCs from a leader or candidate.
所以从更严格的角度来说,是应该在投票后(收到了candidate的请求)进行重新计时。
万分感谢!