精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

MongoDB一次節(jié)點(diǎn)宕機(jī)引發(fā)的思考

運(yùn)維 數(shù)據(jù)庫(kù)運(yùn)維 MongoDB
最近一個(gè) MongoDB 集群環(huán)境中的某節(jié)點(diǎn)異常下電了,導(dǎo)致業(yè)務(wù)出現(xiàn)了中斷,隨即又恢復(fù)了正常。

[[281208]]

簡(jiǎn)介

最近一個(gè) MongoDB 集群環(huán)境中的某節(jié)點(diǎn)異常下電了,導(dǎo)致業(yè)務(wù)出現(xiàn)了中斷,隨即又恢復(fù)了正常。

通過ELK 告警也監(jiān)測(cè)到了業(yè)務(wù)報(bào)錯(cuò)日志。

運(yùn)維部對(duì)于節(jié)點(diǎn)下電的原因進(jìn)行了排查,發(fā)現(xiàn)僅僅是資源分配上的一個(gè)失誤導(dǎo)致。 在解決了問題之后,大家也對(duì)這次中斷的也提出了一些問題:

"當(dāng)前的 MongoDB集群 采用了分片副本集的架構(gòu),其中主節(jié)點(diǎn)發(fā)生故障會(huì)產(chǎn)生多大的影響?"

"MongoDB 副本集不是能自動(dòng)倒換嗎,這個(gè)是不是秒級(jí)的?"

帶著這些問題,下面針對(duì)副本集的自動(dòng)Failover機(jī)制做一些分析。

日志分析

首先可以確認(rèn)的是,這次掉電的是一個(gè)副本集上的主節(jié)點(diǎn),在掉電的時(shí)候,主備關(guān)系發(fā)生了切換。

從另外的兩個(gè)備節(jié)點(diǎn)找到了對(duì)應(yīng)的日志:

備節(jié)點(diǎn)1的日志

  1. 2019-05-06T16:51:11.766+0800 I REPL [ReplicationExecutor] Starting an election, since we've seen no PRIMARY in the past 10000ms 
  2. 2019-05-06T16:51:11.766+0800 I REPL [ReplicationExecutor] conducting a dry run election to see if we could be elected 
  3. 2019-05-06T16:51:11.766+0800 I ASIO [NetworkInterfaceASIO-Replication-0] Connecting to 172.30.129.78:30071 
  4. 2019-05-06T16:51:11.767+0800 I REPL [ReplicationExecutor] VoteRequester(term 3 dry run) received a yes vote from 172.30.129.7:30071; response message: { term: 3, voteGranted: true, reason: "", ok: 1.0 } 
  5. 2019-05-06T16:51:11.767+0800 I REPL [ReplicationExecutor] dry election run succeeded, running for election 
  6. 2019-05-06T16:51:11.768+0800 I ASIO [NetworkInterfaceASIO-Replication-0] Connecting to 172.30.129.78:30071 
  7. 2019-05-06T16:51:11.771+0800 I REPL [ReplicationExecutor] VoteRequester(term 4) received a yes vote from 172.30.129.7:30071; response message: { term: 4, voteGranted: true, reason: "", ok: 1.0 } 
  8. 2019-05-06T16:51:11.771+0800 I REPL [ReplicationExecutor] election succeeded, assuming primary role in term 4 
  9. 2019-05-06T16:51:11.771+0800 I REPL [ReplicationExecutor] transition to PRIMARY 
  10. 2019-05-06T16:51:11.771+0800 I REPL [ReplicationExecutor] Entering primary catch-up mode. 
  11. 2019-05-06T16:51:11.771+0800 I ASIO [NetworkInterfaceASIO-Replication-0] Ending connection to host 172.30.129.78:30071 due to bad connection status; 2 connections to that host remain open 
  12. 2019-05-06T16:51:11.771+0800 I ASIO [NetworkInterfaceASIO-Replication-0] Connecting to 172.30.129.78:30071 
  13. 2019-05-06T16:51:13.350+0800 I REPL [ReplicationExecutor] Error in heartbeat request to 172.30.129.78:30071; ExceededTimeLimit: Couldn't get a connection within the time limit 

備節(jié)點(diǎn)2的日志

  1. 2019-05-06T16:51:12.816+0800 I ASIO [NetworkInterfaceASIO-Replication-0] Ending connection to host 172.30.129.78:30071 due to bad connection status; 0 connections to that host remain open 
  2. 2019-05-06T16:51:12.816+0800 I REPL [ReplicationExecutor] Error in heartbeat request to 172.30.129.78:30071; ExceededTimeLimit: Operation timed out, request was RemoteCommand 72553 -- target:172.30.129.78:30071 db:admin expDate:2019-05-06T16:51:12.816+0800 cmd:{ replSetHeartbeat: "shard0", configVersion: 96911, from: "172.30.129.7:30071", fromId: 1, term: 3 } 
  3. 2019-05-06T16:51:12.821+0800 I REPL [ReplicationExecutor] Member 172.30.129.160:30071 is now in state PRIMARY 

可以看到,備節(jié)點(diǎn)1在 16:51:11 時(shí)主動(dòng)發(fā)起了選舉,并成為了新的主節(jié)點(diǎn),隨即備節(jié)點(diǎn)2在 16:51:12 獲知了最新的主節(jié)點(diǎn)信息,因此可以確認(rèn)此時(shí)主備切換已經(jīng)完成。

同時(shí)在日志中出現(xiàn)的,還有對(duì)于原主節(jié)點(diǎn)(172.30.129.78:30071)大量心跳失敗的信息。

那么,備節(jié)點(diǎn)具體是怎么感知到主節(jié)點(diǎn)已經(jīng) Down 掉的,主備節(jié)點(diǎn)之間的心跳是如何運(yùn)作的,這對(duì)數(shù)據(jù)的同步復(fù)制又有什么影響?

下面,我們挖掘一下 ** 副本集的 自動(dòng)故障轉(zhuǎn)移(Failover)** 機(jī)制

副本集 如何實(shí)現(xiàn) Failover

如下是一個(gè)PSS(一主兩備)架構(gòu)的副本集,主節(jié)點(diǎn)除了與兩個(gè)備節(jié)點(diǎn)執(zhí)行數(shù)據(jù)復(fù)制之外,三個(gè)節(jié)點(diǎn)之間還會(huì)通過心跳感知彼此的存活。

 

MongoDB一次節(jié)點(diǎn)宕機(jī)引發(fā)的思考(源碼剖析)

 

一旦主節(jié)點(diǎn)發(fā)生故障以后,備節(jié)點(diǎn)將在某個(gè)周期內(nèi)檢測(cè)到主節(jié)點(diǎn)處于不可達(dá)的狀態(tài),此后將由其中一個(gè)備節(jié)點(diǎn)事先發(fā)起選舉并最終成為新的主節(jié)點(diǎn)。 這個(gè)檢測(cè)周期 由electionTimeoutMillis 參數(shù)確定,默認(rèn)是10s。

 

MongoDB一次節(jié)點(diǎn)宕機(jī)引發(fā)的思考(源碼剖析)

 

接下來(lái),我們通過一些源碼看看該機(jī)制是如何實(shí)現(xiàn)的:

<<來(lái)自 MongoDB 3.4源碼>>

db/repl/replication_coordinator_impl_heartbeat.cpp

相關(guān)方法

  • ReplicationCoordinatorImpl::_startHeartbeats_inlock 啟動(dòng)各成員的心跳
  • ReplicationCoordinatorImpl::_scheduleHeartbeatToTarget 調(diào)度任務(wù)-(計(jì)劃)向成員發(fā)起心跳
  • ReplicationCoordinatorImpl::_doMemberHeartbeat 執(zhí)行向成員發(fā)起心跳
  • ReplicationCoordinatorImpl::_handleHeartbeatResponse 處理心跳響應(yīng)
  • ReplicationCoordinatorImpl::_scheduleNextLivenessUpdate_inlock 調(diào)度保活狀態(tài)檢查定時(shí)器
  • ReplicationCoordinatorImpl::_cancelAndRescheduleElectionTimeout_inlock 取消并重新調(diào)度選舉超時(shí)定時(shí)器
  • ReplicationCoordinatorImpl::_startElectSelfIfEligibleV1 發(fā)起主動(dòng)選舉

db/repl/topology_coordinator_impl.cpp

相關(guān)方法

  • TopologyCoordinatorImpl::prepareHeartbeatRequestV1 構(gòu)造心跳請(qǐng)求數(shù)據(jù)
  • TopologyCoordinatorImpl::processHeartbeatResponse 處理心跳響應(yīng)并構(gòu)造下一步Action實(shí)例

下面這個(gè)圖,描述了各個(gè)方法之間的調(diào)用關(guān)系

 

MongoDB一次節(jié)點(diǎn)宕機(jī)引發(fā)的思考(源碼剖析)

 

圖-主要關(guān)系

心跳的實(shí)現(xiàn)

首先,在副本集組建完成之后,節(jié)點(diǎn)會(huì)通過ReplicationCoordinatorImpl::_startHeartbeats_inlock方法開始向其他成員發(fā)送心跳:

  1. void ReplicationCoordinatorImpl::_startHeartbeats_inlock() { 
  2.  const Date_t now = _replExecutor.now(); 
  3.  _seedList.clear(); 
  4.  //獲取副本集成員 
  5.  for (int i = 0; i < _rsConfig.getNumMembers(); ++i) { 
  6.  if (i == _selfIndex) { 
  7.  continue
  8.  } 
  9.  //向其他成員發(fā)送心跳 
  10.  _scheduleHeartbeatToTarget(_rsConfig.getMemberAt(i).getHostAndPort(), i, now); 
  11.  } 
  12.  //僅僅是刷新本地的心跳狀態(tài)數(shù)據(jù) 
  13.  _topCoord->restartHeartbeats(); 
  14.  //使用V1的選舉協(xié)議(3.2之后) 
  15.  if (isV1ElectionProtocol()) { 
  16.  for (auto&& slaveInfo : _slaveInfo) { 
  17.  slaveInfo.lastUpdate = _replExecutor.now(); 
  18.  slaveInfo.down = false
  19.  } 
  20.  //調(diào)度保活狀態(tài)檢查定時(shí)器 
  21.  _scheduleNextLivenessUpdate_inlock(); 
  22.  } 

在獲得當(dāng)前副本集的節(jié)點(diǎn)信息后,調(diào)用_scheduleHeartbeatToTarget方法對(duì)其他成員發(fā)送心跳,

這里_scheduleHeartbeatToTarget 的實(shí)現(xiàn)比較簡(jiǎn)單,其真正發(fā)起心跳是由 _doMemberHeartbeat 實(shí)現(xiàn)的,如下:

  1. void ReplicationCoordinatorImpl::_scheduleHeartbeatToTarget(const HostAndPort& target, 
  2.  int targetIndex, 
  3.  Date_t when) { 
  4.  //執(zhí)行調(diào)度,在某個(gè)時(shí)間點(diǎn)調(diào)用_doMemberHeartbeat 
  5.  _trackHeartbeatHandle( 
  6.  _replExecutor.scheduleWorkAt(when
  7.  stdx::bind(&ReplicationCoordinatorImpl::_doMemberHeartbeat, 
  8.  this, 
  9.  stdx::placeholders::_1, 
  10.  target, 
  11.  targetIndex))); 

ReplicationCoordinatorImpl::_doMemberHeartbeat 方法的實(shí)現(xiàn)如下:

  1. void ReplicationCoordinatorImpl::_doMemberHeartbeat(ReplicationExecutor::CallbackArgs cbData, 
  2.  const HostAndPort& target, 
  3.  int targetIndex) { 
  4.  LockGuard topoLock(_topoMutex); 
  5.  //取消callback 跟蹤 
  6.  _untrackHeartbeatHandle(cbData.myHandle); 
  7.  if (cbData.status == ErrorCodes::CallbackCanceled) { 
  8.  return
  9.  } 
  10.  const Date_t now = _replExecutor.now(); 
  11.  BSONObj heartbeatObj; 
  12.  Milliseconds timeout(0); 
  13.  //3.2 以后的版本 
  14.  if (isV1ElectionProtocol()) { 
  15.  const std::pair<ReplSetHeartbeatArgsV1, Milliseconds> hbRequest = 
  16.  _topCoord->prepareHeartbeatRequestV1(now, _settings.ourSetName(), target); 
  17.  //構(gòu)造請(qǐng)求,設(shè)置一個(gè)timeout 
  18.  heartbeatObj = hbRequest.first.toBSON(); 
  19.  timeout = hbRequest.second
  20.  } else { 
  21.  ... 
  22.  } 
  23.  //構(gòu)造遠(yuǎn)程命令 
  24.  const RemoteCommandRequest request( 
  25.  target, "admin", heartbeatObj, BSON(rpc::kReplSetMetadataFieldName << 1), nullptr, timeout); 
  26.  //設(shè)置遠(yuǎn)程命令回調(diào),指向_handleHeartbeatResponse方法 
  27.  const ReplicationExecutor::RemoteCommandCallbackFn callback = 
  28.  stdx::bind(&ReplicationCoordinatorImpl::_handleHeartbeatResponse, 
  29.  this, 
  30.  stdx::placeholders::_1, 
  31.  targetIndex); 
  32.  _trackHeartbeatHandle(_replExecutor.scheduleRemoteCommand(request, callback)); 

上面的代碼中存在的一些細(xì)節(jié):

  • 心跳的超時(shí)時(shí)間,在_topCoord.prepareHeartbeatRequestV1方法中就已經(jīng)設(shè)定好了
  • 具體的算法就是:
  1. **hbTimeout=_rsConfig.getHeartbeatTimeoutPeriodMillis() - alreadyElapsed** 

其中heartbeatTimeoutPeriodMillis是可配置的參數(shù),默認(rèn)是10s, 那么alreadyElapsed是指此前連續(xù)心跳失敗(最多2次)累計(jì)的消耗時(shí)間,在心跳成功響應(yīng)或者超過10s后alreadyElapsed會(huì)置為0。因此可以判斷,隨著心跳失敗次數(shù)的增加,超時(shí)時(shí)間會(huì)越來(lái)越短(心跳更加密集)

心跳執(zhí)行的回調(diào),指向自身的_handleHeartbeatResponse方法,該函數(shù)實(shí)現(xiàn)了心跳響應(yīng)成功、失敗(或是超時(shí))之后的流程處理。

ReplicationCoordinatorImpl::_handleHeartbeatResponse方法的代碼片段:

  1. void ReplicationCoordinatorImpl::_handleHeartbeatResponse( 
  2.  const ReplicationExecutor::RemoteCommandCallbackArgs& cbData, int targetIndex) { 
  3.  LockGuard topoLock(_topoMutex); 
  4.  // remove handle from queued heartbeats 
  5.  _untrackHeartbeatHandle(cbData.myHandle); 
  6.  ... 
  7.  //響應(yīng)成功后 
  8.  if (responseStatus.isOK()) { 
  9.  networkTime = cbData.response.elapsedMillis.value_or(Milliseconds{0}); 
  10.  const auto& hbResponse = hbStatusResponse.getValue(); 
  11.  // 只要primary 心跳響應(yīng)成功,就會(huì)重新調(diào)度 electionTimeout定時(shí)器 
  12.  if (hbResponse.hasState() && hbResponse.getState().primary() && 
  13.  hbResponse.getTerm() == _topCoord->getTerm()) { 
  14.  //取消并重新調(diào)度 electionTimeout定時(shí)器 
  15.  cancelAndRescheduleElectionTimeout(); 
  16.  } 
  17.  } 
  18.  ... 
  19.  //調(diào)用topCoord的processHeartbeatResponse方法處理心跳響應(yīng)狀態(tài),并返回下一步執(zhí)行的Action 
  20.  HeartbeatResponseAction action = _topCoord->processHeartbeatResponse( 
  21.  now, networkTime, target, hbStatusResponse, lastApplied); 
  22.  ... 
  23.  //調(diào)度下一次心跳,時(shí)間間隔采用action提供的信息 
  24.  _scheduleHeartbeatToTarget( 
  25.  target, targetIndex, std::max(now, action.getNextHeartbeatStartDate())); 
  26.  //根據(jù)Action 執(zhí)行處理 
  27.  _handleHeartbeatResponseAction(action, hbStatusResponse, false); 

這里省略了許多細(xì)節(jié),但仍然可以看到,在響應(yīng)心跳時(shí)會(huì)包含這些事情的處理:

對(duì)于主節(jié)點(diǎn)的成功響應(yīng),會(huì)重新調(diào)度 electionTimeout定時(shí)器(取消之前的調(diào)度并重新發(fā)起)

通過_topCoord對(duì)象的processHeartbeatResponse方法解析處理心跳響應(yīng),并返回下一步的Action指示

根據(jù)Action 指示中的下一次心跳時(shí)間設(shè)置下一次心跳定時(shí)任務(wù)

處理Action指示的動(dòng)作

那么,心跳響應(yīng)之后會(huì)等待多久繼續(xù)下一次心跳呢? 在 TopologyCoordinatorImpl::processHeartbeatResponse方法中,實(shí)現(xiàn)邏輯為:

如果心跳響應(yīng)成功,會(huì)等待heartbeatInterval,該值是一個(gè)可配參數(shù),默認(rèn)為2s;

如果心跳響應(yīng)失敗,則會(huì)直接發(fā)送心跳(不等待)。

代碼如下:

  1. HeartbeatResponseAction TopologyCoordinatorImpl::processHeartbeatResponse(...) { 
  2.   
  3.  ... 
  4.  const Milliseconds alreadyElapsed = now - hbStats.getLastHeartbeatStartDate(); 
  5.  Date_t nextHeartbeatStartDate; 
  6.  // 計(jì)算下一次 心跳啟動(dòng)時(shí)間 
  7.  // numFailuresSinceLastStart 對(duì)應(yīng)連續(xù)失敗的次數(shù)(2次以內(nèi)) 
  8.  if (hbStats.getNumFailuresSinceLastStart() <= kMaxHeartbeatRetries && 
  9.  alreadyElapsed < _rsConfig.getHeartbeatTimeoutPeriod()) { 
  10.  // 心跳失敗,不等待,直接重試心跳 
  11.  nextHeartbeatStartDate = now; 
  12.  } else { 
  13.  // 心跳成功,等待一定間隔后再次發(fā)送(一般是2s) 
  14.  nextHeartbeatStartDate = now + heartbeatInterval; 
  15.  } 
  16.  ... 
  17.  // 決定下一步的動(dòng)作,可能發(fā)生 tack over(本備節(jié)點(diǎn)優(yōu)先級(jí)更高,且數(shù)據(jù)與主節(jié)點(diǎn)一樣新時(shí)) 
  18.  HeartbeatResponseAction nextAction; 
  19.  if (_rsConfig.getProtocolVersion() == 0) { 
  20.  ... 
  21.  } else { 
  22.  nextAction = _updatePrimaryFromHBDataV1(memberIndex, originalState, now, myLastOpApplied); 
  23.  } 
  24.  nextAction.setNextHeartbeatStartDate(nextHeartbeatStartDate); 
  25.  return nextAction; 

electionTimeout 定時(shí)器

至此,我們已經(jīng)知道了心跳實(shí)現(xiàn)的一些細(xì)節(jié),默認(rèn)情況下副本集節(jié)點(diǎn)會(huì)每2s向其他節(jié)點(diǎn)發(fā)出心跳(默認(rèn)的超時(shí)時(shí)間是10s)。

如果心跳成功,將會(huì)持續(xù)以2s的頻率繼續(xù)發(fā)送心跳,在心跳失敗的情況下,則會(huì)立即重試心跳(以更短的超時(shí)時(shí)間),一直到心跳恢復(fù)成功或者超過10s的周期。

那么,心跳失敗是如何觸發(fā)主備切換的呢,electionTimeout 又是如何發(fā)揮作用?

在前面的過程中,與electionTimeout參數(shù)相關(guān)兩個(gè)方法如下,它們也分別對(duì)應(yīng)了單獨(dú)的定時(shí)器:

ReplicationCoordinatorImpl::_scheduleNextLivenessUpdate_inlock 發(fā)起保活狀態(tài)檢查定時(shí)器

ReplicationCoordinatorImpl::_cancelAndRescheduleElectionTimeout_inlock 重新發(fā)起選舉超時(shí)定時(shí)器

第一個(gè)是 _scheduleNextLivenessUpdate_inlock這個(gè)函數(shù),它的作用在于保活狀態(tài)檢測(cè),如下:

  1. void ReplicationCoordinatorImpl::_scheduleNextLivenessUpdate_inlock() { 
  2.  //僅僅支持3.2+ 
  3.  if (!isV1ElectionProtocol()) { 
  4.  return
  5.  } 
  6.   
  7.  // earliestDate 取所有節(jié)點(diǎn)中更新時(shí)間最早的(以盡可能早的發(fā)現(xiàn)問題) 
  8.  // electionTimeoutPeriod 默認(rèn)為 10s 
  9.  auto nextTimeout = earliestDate + _rsConfig.getElectionTimeoutPeriod(); 
  10.   
  11.  // 設(shè)置超時(shí)回調(diào)函數(shù)為 _handleLivenessTimeout 
  12.  auto cbh = _scheduleWorkAt(nextTimeout, 
  13.  stdx::bind(&ReplicationCoordinatorImpl::_handleLivenessTimeout, 
  14.  this, 
  15.  stdx::placeholders::_1)); 

因此,在大約10s后,如果沒有什么意外,_handleLivenessTimeout將會(huì)被觸發(fā),如下:

  1. void ReplicationCoordinatorImpl::_handleLivenessTimeout(...) { 
  2.  ... 
  3.  for (auto&& slaveInfo : _slaveInfo) { 
  4.  ... 
  5.  //lastUpdate 不夠新(小于electionTimeout) 
  6.  if (now - slaveInfo.lastUpdate >= _rsConfig.getElectionTimeoutPeriod()) { 
  7.  ... 
  8.  //在保活周期后仍然未更新節(jié)點(diǎn),置為down狀態(tài) 
  9.  slaveInfo.down = true
  10.  //如果當(dāng)前節(jié)點(diǎn)是主,且檢測(cè)到某個(gè)備節(jié)點(diǎn)為down的狀態(tài),進(jìn)入memberdown流程 
  11.  if (_memberState.primary()) { 
  12.   
  13.  //調(diào)用_topCoord的setMemberAsDown方法,記錄某個(gè)備節(jié)點(diǎn)不可達(dá),并獲得下一步的指示 
  14.  //當(dāng)大多數(shù)節(jié)點(diǎn)不可見時(shí),這里會(huì)獲得讓自身降備的指示 
  15.  HeartbeatResponseAction action = 
  16.  _topCoord->setMemberAsDown(now, memberIndex, _getMyLastDurableOpTime_inlock()); 
  17.  //執(zhí)行指示 
  18.  _handleHeartbeatResponseAction(action
  19.  makeStatusWith<ReplSetHeartbeatResponse>(), 
  20.  true); 
  21.  } 
  22.  } 
  23.  } 
  24.  //繼續(xù)調(diào)度下一個(gè)周期 
  25.  _scheduleNextLivenessUpdate_inlock(); 

可以看到,這個(gè)定時(shí)器主要是用于實(shí)現(xiàn)主節(jié)點(diǎn)對(duì)其他節(jié)點(diǎn)的保活探測(cè)邏輯:

當(dāng)主節(jié)點(diǎn)發(fā)現(xiàn)大多數(shù)節(jié)點(diǎn)不可達(dá)時(shí)(不滿足大多數(shù)原則),將會(huì)讓自己執(zhí)行降備

因此,在一個(gè)三節(jié)點(diǎn)的副本集中,其中兩個(gè)備節(jié)點(diǎn)掛掉后,主節(jié)點(diǎn)會(huì)自動(dòng)降備。 這樣的設(shè)計(jì)主要是為了避免產(chǎn)生意外的數(shù)據(jù)不一致情況產(chǎn)生。

 

MongoDB一次節(jié)點(diǎn)宕機(jī)引發(fā)的思考(源碼剖析)

 

圖- 主自動(dòng)降備

第二個(gè)是_cancelAndRescheduleElectionTimeout_inlock函數(shù),這里則是實(shí)現(xiàn)自動(dòng)Failover的關(guān)鍵了,

它的邏輯中包含了一個(gè)選舉定時(shí)器,代碼如下:

  1. void ReplicationCoordinatorImpl::_cancelAndRescheduleElectionTimeout_inlock() { 
  2.  //如果上一個(gè)定時(shí)器已經(jīng)啟用了,則直接取消 
  3.  if (_handleElectionTimeoutCbh.isValid()) { 
  4.  LOG(4) << "Canceling election timeout callback at " << _handleElectionTimeoutWhen; 
  5.  _replExecutor.cancel(_handleElectionTimeoutCbh); 
  6.  _handleElectionTimeoutCbh = CallbackHandle(); 
  7.  _handleElectionTimeoutWhen = Date_t(); 
  8.  } 
  9.  //僅支持3.2后的V1版本 
  10.  if (!isV1ElectionProtocol()) { 
  11.  return
  12.  } 
  13.  //僅備節(jié)點(diǎn)可執(zhí)行 
  14.  if (!_memberState.secondary()) { 
  15.  return
  16.  } 
  17.  ... 
  18.  //是否可以選舉 
  19.  if (!_rsConfig.getMemberAt(_selfIndex).isElectable()) { 
  20.  return
  21.  } 
  22.  //檢測(cè)周期,由 electionTimeout + randomOffset 
  23.  //randomOffset是隨機(jī)偏移量,默認(rèn)為 0~0.15*ElectionTimeoutPeriod = 0~1.5s 
  24.  Milliseconds randomOffset = _getRandomizedElectionOffset(); 
  25.  auto now = _replExecutor.now(); 
  26.  auto when = now + _rsConfig.getElectionTimeoutPeriod() + randomOffset; 
  27.   
  28.  LOG(4) << "Scheduling election timeout callback at " << when
  29.  _handleElectionTimeoutWhen = when
  30.  //觸發(fā)調(diào)度,時(shí)間為 now + ElectionTimeoutPeriod + randomOffset 
  31.  _handleElectionTimeoutCbh = 
  32.  _scheduleWorkAt(when
  33.  stdx::bind(&ReplicationCoordinatorImpl::_startElectSelfIfEligibleV1, 
  34.  this, 
  35.  StartElectionV1Reason::kElectionTimeout)); 

上面代碼展示了這個(gè)選舉定時(shí)器的邏輯,在每一個(gè)檢測(cè)周期中,定時(shí)器都會(huì)嘗試執(zhí)行超時(shí)回調(diào),

而回調(diào)函數(shù)指向的是_startElectSelfIfEligibleV1,這里面就實(shí)現(xiàn)了主動(dòng)發(fā)起選舉的功能,

如果心跳響應(yīng)成功,通過cancelAndRescheduleElectionTimeout調(diào)用將直接取消當(dāng)次的超時(shí)回調(diào)(即不會(huì)發(fā)起選舉)

如果心跳響應(yīng)遲遲不能成功,那么定時(shí)器將被觸發(fā),進(jìn)而導(dǎo)致備節(jié)點(diǎn)發(fā)起選舉并成為新的主節(jié)點(diǎn)!

同時(shí),這個(gè)回調(diào)方法(產(chǎn)生選舉)被觸發(fā)必須要滿足以下條件:

  1. 當(dāng)前是備節(jié)點(diǎn)
  2. 當(dāng)前節(jié)點(diǎn)具備選舉權(quán)限
  3. 在檢測(cè)周期內(nèi)仍然沒有與主節(jié)點(diǎn)心跳成功

這其中的檢測(cè)周期略大于electionTimeout(10s),加入一個(gè)隨機(jī)偏移量后大約是10-11.5s內(nèi),猜測(cè)這樣的設(shè)計(jì)是為了錯(cuò)開多個(gè)備節(jié)點(diǎn)主動(dòng)選舉的時(shí)間,提升成功率。

最后,將整個(gè)自動(dòng)選舉切換的邏輯梳理后,如下圖所示:

 

MongoDB一次節(jié)點(diǎn)宕機(jī)引發(fā)的思考(源碼剖析)

 

圖-超時(shí)自動(dòng)選舉

業(yè)務(wù)影響評(píng)估

副本集發(fā)生主備切換的情況下,不會(huì)影響現(xiàn)有的讀操作,只會(huì)影響寫操作。 如果使用3.6及以上版本的驅(qū)動(dòng),可以通過開啟retryWrite來(lái)降低影響。

但是如果主節(jié)點(diǎn)是屬于強(qiáng)制掉電,那么整個(gè) Failover 過程將會(huì)變長(zhǎng),很可能需要在Election定時(shí)器超時(shí)后才被副本集感知并恢復(fù),這個(gè)時(shí)間窗口會(huì)在12s以內(nèi)。

此外還需要考慮客戶端或mongos對(duì)于副本集角色的監(jiān)視和感知行為。但總之在問題恢復(fù)之前,對(duì)于原主節(jié)點(diǎn)的任何讀寫都會(huì)發(fā)生超時(shí)。

因此,對(duì)于極為重要的業(yè)務(wù),建議最好在業(yè)務(wù)層面做一些防護(hù)策略,比如設(shè)計(jì)重試機(jī)制。

責(zé)任編輯:武曉燕 來(lái)源: 今日頭條
相關(guān)推薦

2018-12-27 09:09:35

2022-11-29 21:26:26

跨域配置

2019-01-16 09:20:42

架構(gòu)設(shè)計(jì)JVM FullGC宕機(jī)事故

2013-03-05 10:05:52

2015-07-17 10:05:03

面試思考

2021-11-01 17:29:02

Windows系統(tǒng)Fork

2017-08-24 17:37:18

DNS緩存分析

2019-10-09 11:42:10

分布式取錢異步流程

2024-05-13 08:37:17

炫技H5UI

2023-07-13 09:12:37

CNCF項(xiàng)目云原生

2019-06-25 14:44:11

分布式事務(wù)數(shù)據(jù)庫(kù)

2022-12-26 10:42:00

康普中國(guó)

2018-09-12 09:07:43

服務(wù)器數(shù)據(jù)RAID5

2021-11-22 08:33:27

微信聊天離婚

2021-03-17 00:17:16

命令應(yīng)急響應(yīng)

2020-01-06 09:43:14

賠償TSB遷移

2018-07-16 22:29:29

代碼迭代質(zhì)量

2022-09-03 18:29:49

開發(fā)技術(shù)

2012-07-05 09:54:04

Amazon宕機(jī)

2022-06-14 08:00:28

切換包管理器版本
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

99re视频精品| 日韩夫妻性生活xx| 婷婷综合在线观看| 国产一区精品视频| 久久久免费高清视频| 性欧美lx╳lx╳| 91精品1区2区| 自拍偷拍99| 亚洲男人第一天堂| 亚洲综合日本| 深夜成人在线观看| 国产精品99精品无码视亚| av福利在线导航| 99国产麻豆精品| 国产精品吴梦梦| 久久免费小视频| 免费欧美激情| 91精品国产日韩91久久久久久| 日本福利视频在线观看| 亚洲色图另类小说| 激情深爱一区二区| 欧美性受xxxx白人性爽| 午夜国产小视频| 精品三级av| 欧美日韩国产一二三| 精品无码一区二区三区爱欲| melody高清在线观看| 国产a久久麻豆| 国产精品入口夜色视频大尺度| 久久久久亚洲av无码专区| 精品一区亚洲| 欧美本精品男人aⅴ天堂| 欧美在线观看视频网站| 黄页网站在线观看免费| 国产精品天美传媒| 久久九九视频| 国产福利第一页| 日韩成人av影视| 97国产精品人人爽人人做| 91香蕉视频网| 精品国产91| 亚洲精品电影在线观看| 日本亚洲一区二区三区| 成人国产一区二区三区精品麻豆| 一区二区三区美女| 亚洲一区二区在线免费观看| 毛片在线播放网站| 成人免费黄色大片| 亚洲一区制服诱惑| 一起草av在线| 蜜桃在线一区二区三区| 国产成人av在线播放| 亚洲精品视频在线观看免费视频| 中文字幕人成人乱码| 伊人一区二区三区久久精品| 中文字幕在线播放视频| 国产成人福利av| 日韩精品中文字幕在线不卡尤物| 亚洲男人天堂av在线| 国产精品videossex撒尿| 色婷婷综合激情| 18岁网站在线观看| 国产亚洲成av人片在线观看| 亚洲一二三区视频在线观看| 精品91一区二区三区| 黄色片网站在线观看| 中文字幕一区二区三区视频 | 国产亚洲综合视频| 久久青草伊人| 欧美日韩在线一区| 成年网站在线免费观看| 最新日韩精品| 在线亚洲高清视频| 激情视频免费网站| 999精品视频在线观看| 777奇米四色成人影色区| 伊人影院综合在线| 国产精品国产亚洲精品| 日韩一区二区免费电影| 日批免费观看视频| 蜜桃一区av| 日韩电影视频免费| 国产成人无码精品久久二区三| 国产一区二区三区电影在线观看| 在线观看国产精品淫| 九九热久久免费视频| 91tv官网精品成人亚洲| 欧美激情2020午夜免费观看| 欧美偷拍第一页| 欧美综合在线视频观看| 久久精品视频在线播放| 久久午夜无码鲁丝片| 国产亚洲高清视频| 国产精品一二三在线| 99精品久久久久久中文字幕| kk眼镜猥琐国模调教系列一区二区| 久久免费视频1| 在线播放麻豆| 亚洲一区在线看| 国产精品人人妻人人爽人人牛| 欧美三级电影网址| 欧美不卡一区二区三区| 国产全是老熟女太爽了| 久久精品国产68国产精品亚洲| 九色成人免费视频| 亚洲av中文无码乱人伦在线视色| 老司机免费视频一区二区三区| 91九色视频在线观看| 三级毛片在线免费看| 国产精品二区一区二区aⅴ污介绍| 国产911在线观看| 国产高清不卡| 日韩三级中文字幕| 欧美偷拍一区二区三区| 国内精品美女在线观看| 国产精品成人观看视频国产奇米| 性生活三级视频| 国产亚洲精品久| 99在线免费视频观看| 91国拍精品国产粉嫩亚洲一区| 欧美成人在线直播| 91麻豆制片厂| 亚洲一区观看| 成人情视频高清免费观看电影| 国产黄色片在线观看| 亚洲成av人片一区二区梦乃| 色乱码一区二区三区在线| 免费看久久久| 欧美高清一级大片| 一级做a爱片性色毛片| 久久久噜噜噜久久中文字幕色伊伊 | 伊人网综合在线| 99久免费精品视频在线观看| 无码人妻精品一区二区三区99v| 丝袜美腿一区| 亚洲第一男人av| 丝袜 亚洲 另类 欧美 重口| 青青草精品视频| 欧美激情视频一区二区三区| gogo高清午夜人体在线| 欧美一区二区精品在线| 国产又粗又长又黄的视频| 麻豆9191精品国产| 国产一区二区三区四区五区加勒比| 黄色网在线看| 欧美日韩亚洲综合一区| 一级片视频免费看| 久久大逼视频| 免费成人看片网址| 国产直播在线| 日韩成人高清在线| 国内精品福利视频| 91免费看片在线观看| 亚洲熟妇国产熟妇肥婆| 高清精品视频| 午夜精品久久久久久久久久久久久| www国产一区| 一区二区三区欧美激情| 国产高清视频网站| 秋霞欧美视频| 国产女人精品视频| 麻豆视频在线免费观看| 欧美日本在线一区| 老司机成人免费视频| 狠狠色丁香婷综合久久| 制服诱惑一区| 精品国产亚洲日本| 欧美人成在线视频| www.五月婷婷| 欧美日韩免费观看中文| 亚洲狠狠婷婷综合久久久久图片| 亚洲尤物精选| 日本视频精品一区| 日韩专区视频| 久久成人av网站| 性欧美8khd高清极品| 五月婷婷另类国产| 手机av免费看| 久久99精品国产麻豆不卡| 国产精品h视频| 成人另类视频| 26uuu国产精品视频| 国产三级电影在线| 欧美一区二区视频网站| 日操夜操天天操| 久久久久国色av免费看影院| 伊人国产在线视频| 欧美极品一区二区三区| 精品无码久久久久久久动漫| 黄色在线观看www| 中文在线资源观看视频网站免费不卡 | 51精产品一区一区三区| 国模精品一区二区三区| 欧美黑人巨大xxxxx| 久久久av免费| 天堂成人在线| 欧美美女黄视频| 日韩污视频在线观看| 国产精品毛片大码女人| 国产精品亚洲一区二区无码| 久久九九免费| 男女裸体影院高潮| 特黄特色欧美大片| 91精品视频在线看| 岛国av在线播放| 日韩中文字幕网| 天堂网在线播放| 欧美日韩国产大片| 日韩无码精品一区二区三区| 国产精品不卡在线观看| 久久人人爽人人人人片| 久久99久久99| 97xxxxx| 午夜久久美女| 亚洲国产精品www| 久久视频在线观看| 成人有码在线视频| 欧美成人性网| 国内精品模特av私拍在线观看| 在线激情网站| 亚洲久久久久久久久久久| 国产成人精品亚洲精品色欲| 欧美性大战久久久久久久 | 免费在线国产| 精品三级av在线| 亚洲一区二区三区高清视频| 精品久久久中文| 欧美成人精品欧美一级私黄| 国产日韩欧美亚洲| 午夜久久久久久久| 粉嫩嫩av羞羞动漫久久久| www.com黄色片| 久久中文欧美| 波多野结衣家庭教师在线播放| 欧美成人一品| 亚洲欧美一二三| 不卡av一区二区| 欧美日韩精品不卡| 日韩激情网站| 国模精品一区二区三区| jizz18欧美18| 91视频免费在线观看| 久久亚洲资源中文字| 国产精品福利无圣光在线一区| 看黄在线观看| 97在线视频国产| 123区在线| 久久久久久九九九| 色婷婷在线播放| 欧美高清视频在线播放| 丝袜综合欧美| 久99久在线视频| 99福利在线| 美女av一区二区| 顶级网黄在线播放| 麻豆乱码国产一区二区三区| 国产丝袜在线| 九九精品在线播放| 日本h片在线观看| 欧美黑人一级爽快片淫片高清| 欧美寡妇性猛交xxx免费| 美女国内精品自产拍在线播放 | 97视频在线观看亚洲| av资源在线| 91av在线不卡| 亚洲深夜视频| 国产成人精品视频在线观看| 欧美va在线观看| 国产免费一区视频观看免费| 国产aa精品| 国产精品毛片一区视频| 欧美日韩一区二区三区在线电影 | 92久久精品一区二区| 欧美日韩国产片| 国产情侣自拍小视频| 欧美成人乱码一区二区三区| 少妇高潮一区二区三区69| 日韩成人在线视频网站| 蜜桃视频在线免费| 日日骚久久av| 日本在线观看高清完整版| 国内精品小视频在线观看| 在线免费日韩片| 国产精品久久久亚洲| 成人自拍视频| 国产精品夜夜夜一区二区三区尤| 香蕉久久夜色精品国产更新时间 | 亚洲成人自拍一区| 男人日女人网站| 欧美性感一区二区三区| 国产黄色小视频在线观看| 精品福利在线导航| 精品乱码一区二区三四区视频| 最近更新的2019中文字幕| 特级毛片在线| 国产成人自拍视频在线观看| 99久久999| 久久av一区二区三区漫画| 色婷婷综合网| 每日在线观看av| 日本免费在线视频不卡一不卡二| 一个人看的视频www| www精品美女久久久tv| 亚洲AV成人无码精电影在线| 精品久久久久久久久久久久| 亚洲无码久久久久| 亚洲精品videossex少妇| 在线观看黄色av| 午夜精品一区二区三区视频免费看| 成人黄色图片网站| 国产一区二区三区四区五区在线| 93在线视频精品免费观看| 欧美视频在线播放一区| 国产在线观看一区二区| 国内精品久久99人妻无码| 亚洲欧美日韩在线| 黄色av一级片| 亚洲成av人片在线观看香蕉| 欧美激情免费| 日本高清+成人网在线观看| 欧美成人精品午夜一区二区| 欧洲精品久久| 伊人久久久大香线蕉综合直播| 黄色手机在线视频| 久久综合av免费| 国产在线免费视频| 8v天堂国产在线一区二区| 国产大学生校花援交在线播放| 97国产真实伦对白精彩视频8| 国产一区二区三区国产精品| 亚洲.欧美.日本.国产综合在线| 最新日韩在线| 国产精品91av| 综合欧美一区二区三区| 日韩不卡高清视频| 亚洲美女精品成人在线视频| 1区2区3区在线| 高清国产在线一区| 中文字幕免费一区二区| 亚洲欧美日本一区二区| 中文乱码免费一区二区| 成人a v视频| 亚洲美女av黄| 小h片在线观看| 欧美激情论坛| 天堂蜜桃91精品| 人妻精品久久久久中文字幕| 午夜激情一区二区| 男人天堂网在线视频| 久久久久国色av免费观看性色| 国产色99精品9i| 婷婷视频在线播放| 狠狠色综合播放一区二区| 欧美xxxooo| 日韩一区二区三免费高清| 香蕉久久aⅴ一区二区三区| 亚洲va欧美va在线观看| 一区二区中文字| 涩多多在线观看| 亚洲女同一区二区| 精品人妻无码一区二区色欲产成人 | 色综合蜜月久久综合网| 久久撸在线视频| 中文字幕一区二区三区精华液| 国产又爽又黄免费软件| 超薄丝袜一区二区| 中文字幕区一区二区三| 亚洲国产精品无码观看久久| 99久久免费精品高清特色大片| 精品欧美一区二区三区免费观看| 亚洲精品日韩丝袜精品| 精品欧美一区二区三区在线观看| 色综合久久久久久久久五月| 看国产成人h片视频| 日韩视频中文字幕在线观看| 精品久久一二三区| 美女在线视频免费| 欧美日韩一区在线观看视频| 麻豆一区二区99久久久久| 性色av无码久久一区二区三区| 日韩亚洲欧美综合| 国产福利片在线观看| 日韩欧美精品一区二区三区经典 | 国产精品久久久久久中文字| 99久久精品国产亚洲精品| 老司机av网站| 欧美性xxxxxxxxx| 天堂中文8资源在线8| 风间由美久久久| 久久亚洲视频| caoporn91| 日韩精品www| 日本一区二区三区中文字幕| www.日本在线视频| 国产视频一区二区在线| 99热这里只有精品在线观看| 91精品国产高清久久久久久91| 欧美色女视频| 中文字幕99页| 欧美日韩在线综合|