| 
                         代码如下: 
- 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(); 
 - } 
 
  
可以看到,这个定时器主要是用于实现主节点对其他节点的保活探测逻辑: 
当主节点发现大多数节点不可达时(不满足大多数原则),将会让自己执行降备                         (编辑:滁州站长网) 
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! 
                     |