代码如下:
- HeartbeatResponseAction TopologyCoordinatorImpl::processHeartbeatResponse(...) {
-
- ...
- const Milliseconds alreadyElapsed = now - hbStats.getLastHeartbeatStartDate();
- Date_t nextHeartbeatStartDate;
- // 计算下一次 心跳启动时间
- // numFailuresSinceLastStart 对应连续失败的次数(2次以内)
- if (hbStats.getNumFailuresSinceLastStart() <= kMaxHeartbeatRetries &&
- alreadyElapsed < _rsConfig.getHeartbeatTimeoutPeriod()) {
- // 心跳失败,不等待,直接重试心跳
- nextHeartbeatStartDate = now;
- } else {
- // 心跳成功,等待一定间隔后再次发送(一般是2s)
- nextHeartbeatStartDate = now + heartbeatInterval;
- }
- ...
- // 决定下一步的动作,可能发生 tack over(本备节点优先级更高,且数据与主节点一样新时)
- HeartbeatResponseAction nextAction;
- if (_rsConfig.getProtocolVersion() == 0) {
- ...
- } else {
- nextAction = _updatePrimaryFromHBDataV1(memberIndex, originalState, now, myLastOpApplied);
- }
- nextAction.setNextHeartbeatStartDate(nextHeartbeatStartDate);
- return nextAction;
- }
electionTimeout 定时器
至此,我们已经知道了心跳实现的一些细节,默认情况下副本集节点会每2s向其他节点发出心跳(默认的超时时间是10s)。
如果心跳成功,将会持续以2s的频率继续发送心跳,在心跳失败的情况下,则会立即重试心跳(以更短的超时时间),一直到心跳恢复成功或者超过10s的周期。
那么,心跳失败是如何触发主备切换的呢,electionTimeout 又是如何发挥作用?
在前面的过程中,与electionTimeout参数相关两个方法如下,它们也分别对应了单独的定时器:
ReplicationCoordinatorImpl::_scheduleNextLivenessUpdate_inlock 发起保活状态检查定时器
ReplicationCoordinatorImpl::_cancelAndRescheduleElectionTimeout_inlock 重新发起选举超时定时器
第一个是 _scheduleNextLivenessUpdate_inlock这个函数,它的作用在于保活状态检测,如下:
- void ReplicationCoordinatorImpl::_scheduleNextLivenessUpdate_inlock() {
- //仅仅支持3.2+
- if (!isV1ElectionProtocol()) {
- return;
- }
-
- // earliestDate 取所有节点中更新时间最早的(以尽可能早的发现问题)
- // electionTimeoutPeriod 默认为 10s
- auto nextTimeout = earliestDate + _rsConfig.getElectionTimeoutPeriod();
-
- // 设置超时回调函数为 _handleLivenessTimeout
- auto cbh = _scheduleWorkAt(nextTimeout,
- stdx::bind(&ReplicationCoordinatorImpl::_handleLivenessTimeout,
- this,
- stdx::placeholders::_1));
- }
因此,在大约10s后,如果没有什么意外,_handleLivenessTimeout将会被触发,如下:
- void ReplicationCoordinatorImpl::_handleLivenessTimeout(...) {
- ...
- for (auto&& slaveInfo : _slaveInfo) {
- ...
- //lastUpdate 不够新(小于electionTimeout)
- if (now - slaveInfo.lastUpdate >= _rsConfig.getElectionTimeoutPeriod()) {
- ...
- //在保活周期后仍然未更新节点,置为down状态
- slaveInfo.down = true;
- //如果当前节点是主,且检测到某个备节点为down的状态,进入memberdown流程
- if (_memberState.primary()) {
-
- //调用_topCoord的setMemberAsDown方法,记录某个备节点不可达,并获得下一步的指示
- //当大多数节点不可见时,这里会获得让自身降备的指示
- HeartbeatResponseAction action =
- _topCoord->setMemberAsDown(now, memberIndex, _getMyLastDurableOpTime_inlock());
- //执行指示
- _handleHeartbeatResponseAction(action,
- makeStatusWith<ReplSetHeartbeatResponse>(),
- true);
- }
- }
- }
- //继续调度下一个周期
- _scheduleNextLivenessUpdate_inlock();
- }
可以看到,这个定时器主要是用于实现主节点对其他节点的保活探测逻辑:
当主节点发现大多数节点不可达时(不满足大多数原则),将会让自己执行降备 (编辑:威海站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|