加入收藏 | 设为首页 | 会员中心 | 我要投稿 威海站长网 (https://www.0631zz.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

MongoDB一次节点宕机引发的思考

发布时间:2019-11-05 07:23:48 所属栏目:MySql教程 来源:java架构coid
导读:简介 最近一个 MongoDB 集群环境中的某节点异常下电了,导致业务出现了中断,随即又恢复了正常。 通过ELK 告警也监测到了业务报错日志。 运维部对于节点下电的原因进行了排查,发现仅仅是资源分配上的一个失误导致。 在解决了问题之后,大家也对这次中断的

因此,在一个三节点的副本集中,其中两个备节点挂掉后,主节点会自动降备。 这样的设计主要是为了避免产生意外的数据不一致情况产生。

MongoDB一次节点宕机引发的思考(源码剖析)

图- 主自动降备

第二个是_cancelAndRescheduleElectionTimeout_inlock函数,这里则是实现自动Failover的关键了,

它的逻辑中包含了一个选举定时器,代码如下:

  1. void ReplicationCoordinatorImpl::_cancelAndRescheduleElectionTimeout_inlock() { 
  2.  //如果上一个定时器已经启用了,则直接取消 
  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.  //仅备节点可执行 
  14.  if (!_memberState.secondary()) { 
  15.  return; 
  16.  } 
  17.  ... 
  18.  //是否可以选举 
  19.  if (!_rsConfig.getMemberAt(_selfIndex).isElectable()) { 
  20.  return; 
  21.  } 
  22.  //检测周期,由 electionTimeout + randomOffset 
  23.  //randomOffset是随机偏移量,默认为 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.  //触发调度,时间为 now + ElectionTimeoutPeriod + randomOffset 
  31.  _handleElectionTimeoutCbh = 
  32.  _scheduleWorkAt(when, 
  33.  stdx::bind(&ReplicationCoordinatorImpl::_startElectSelfIfEligibleV1, 
  34.  this, 
  35.  StartElectionV1Reason::kElectionTimeout)); 

上面代码展示了这个选举定时器的逻辑,在每一个检测周期中,定时器都会尝试执行超时回调,

而回调函数指向的是_startElectSelfIfEligibleV1,这里面就实现了主动发起选举的功能,

如果心跳响应成功,通过cancelAndRescheduleElectionTimeout调用将直接取消当次的超时回调(即不会发起选举)

如果心跳响应迟迟不能成功,那么定时器将被触发,进而导致备节点发起选举并成为新的主节点!

同时,这个回调方法(产生选举)被触发必须要满足以下条件:

  1. 当前是备节点
  2. 当前节点具备选举权限
  3. 在检测周期内仍然没有与主节点心跳成功

这其中的检测周期略大于electionTimeout(10s),加入一个随机偏移量后大约是10-11.5s内,猜测这样的设计是为了错开多个备节点主动选举的时间,提升成功率。

最后,将整个自动选举切换的逻辑梳理后,如下图所示:

MongoDB一次节点宕机引发的思考(源码剖析)

图-超时自动选举

业务影响评估

副本集发生主备切换的情况下,不会影响现有的读操作,只会影响写操作。 如果使用3.6及以上版本的驱动,可以通过开启retryWrite来降低影响。

但是如果主节点是属于强制掉电,那么整个 Failover 过程将会变长,很可能需要在Election定时器超时后才被副本集感知并恢复,这个时间窗口会在12s以内。

此外还需要考虑客户端或mongos对于副本集角色的监视和感知行为。但总之在问题恢复之前,对于原主节点的任何读写都会发生超时。

因此,对于极为重要的业务,建议最好在业务层面做一些防护策略,比如设计重试机制。

(编辑:威海站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读