一次MongoDB故障的复盘

  • 时间:
  • 浏览:3
  • 来源:5分快乐8APP下载_5分快乐8APP官方

接下来尝试分析为甚会经常经常出现主从延迟,从之前 梳理的集群具体情况来看,除去主从延迟和local.oplog.rs的slow query,一些指标均十分健康(并之前 )。

当时并且感觉到该服务使用游标的法律法律依据居于不妥,还未能完整版与难题关联起来,记得上文中提到当时的整体常用监控指标都十分“健康”(这里埋下了有两个伏笔),此时从客户处有获知了另有两个监控指标–cursor数,客户告知当时主节点cursor总数为780k+个。

集群节点间网络延迟(客户网络工程师反馈节点间网络正常,该将会排除)

QPS居于低位运行,且业务场景读远大与写

Cache Activitiy稳定无暴增

同步业务代码在建立cursor时,使用了tailable,awaitData,且noCursorTimeout的定义,致使cursor在业务没人主动close的具体情况下,将永久居于。(有之前 此时cursor监听在primary节点中,后续朋友 新增了hidden member用于该业务的请求)。

而后在ISODate(“2018-10-24T07:00:80Z”)才进行了下有两个写操作b

而上层业务将A、B有两个接口的调用包装后的场景将会SecondaryPreferred的原困,原困B接口异常,最终影响了业务的正常对外服务。

背景(简单介绍背景具体情况)

不调整接口B的逻辑,在上层调用接口A和B之间加一层保护,通过业务的手段处理在短时间内进行连续的调用,通过业务价值形式的微调拉长A与B接口调用之间的时间轴,如:先交由用户配置所需字段,在提交时再进行任务_id的判断与绑定

在此,朋友 对故障的排查进行一次复盘。

不用 看多上述慢查询几次特点:

主要的慢查询主要的条件为如下,大多为getmore。

此时primary的optimeDate为ISODate(“2018-10-24T07:00:80Z”),而将会朋友 执行该命令的之前 各个从节点完成同步,所以 各个从节点的optimeDate为ISODate(“2018-10-24T07:00:05Z”)。于是乎朋友 得到了另有两个的返回

当时涉及到了主从延迟,慢查询,cursor的不当使用等mongodb难题,本文将从这几次方面全面复盘整个故障的排查过程,其中暗含了如下内容:

不过朋友 也需用额外注意,该值不为0本身能80%代表系统居于主从延迟难题。朋友 先来看看db.printSlaveReplicationInfo()的结果是怎么能不能获取的。

朋友 不用 看多,基准时间是primary节点的optimeDate(将其定义为startOptimeDate),各个从节点的延迟是按照startOptimeDate – st(也并且各个从节点的optimeDate)进行计算(不包括arbiter)。

slow query内getmore居于你这个 属性。

根据迟来的监控指标确认cursor的异常并分析

回归到此次故障的场景,其实db.printSlaveReplicationInfo()居于不准确的将会,有之前 以当时的pqs具体情况来判断,应该是真实经常经常出现了主从延迟。

接下来朋友 将目光聚焦到了local.oplog.rs的慢查询上。

SecondaryPreferred,将接口B的请求发向Primary。

深究与排查

在朋友 将SecondaryPreferred的配置归还后,上层业务恢复了正常。朋友 也辗转获得了客户处mongodb集群的每种监控信息、具体情况等。

而代码中游标加入了你这个 属性

主节点有小量并发写原困从节点无法及时追上(当时qps居于低位,replWriter为默认系统进程数,不应居于瓶颈,暂时排除)

不过这反而致使整个排查过程变得更加有分享和借鉴价值。在这里分享给朋友 希望不用 让朋友 处理踩坑。

梳理后总结为:

db.printSlaveReplicationInfo()所体现的主从延迟本身一定真的代表延迟,有之前 该监控指标任何之前 都需用提起120%的关注度。

该服务异常重启多次造成了primary中cursor的堆积。

此时朋友 正好在1ms后于primary节点中执行了db.printSlaveReplicationInfo()

验证2:在tailable,awaitData和noCursorTimeout定义下,服务异常重启会原困cursor不被释放,进而造成cursor堆积。

流量稳定无暴增

合理利用读写分离,MongoDB的读写分离并之前 真正意义上的将读写压力完整版分离,需用明确业务对于数据一致性的需求,一致性要求强的场景处理SecondaryPreferred将会通过业务价值形式的调整处理该难题。

朋友 知道oplog是没人严格意义上的索引,所以 类事游标在第一次建立的过之前 比较耗时,持续trace到最后的末尾的过之前 居于tailabled和awaitData具体情况,此时实时trace数据的getmore就应该居于相对稳定的快速具体情况。

主从延迟分析与排查,并通过每种mongo源码佐证推断

调用接口A(可简单认为insert了一根数据a)

临时应对与考量

朋友 知道MongoDB的主从同步为异步同步,主从节点之间延迟在所难免,有之前 正常具体情况下延迟时间大多为毫秒级别,大多不用影响到正常业务。此时的难题透露着有两个信息,该MongoDB集群居于异常,有之前 将会第一时间无法获取集群具体情况,具体的异常暂时无从得知。

将会该服务采用pm2进行服务运价值形式管理,朋友 不断向其发送异常关闭的signal,pm2在其error后不断重启。期间观察db.serverStatus().metrics.cursor具体情况,发现db.serverStatus().metrics.cursor.open.noTimeout值持续上升堆积。确认了cursor堆积的原困。

在初步获取到了结论后,朋友 刚开始进行相应的验证。

归还SecondaryPreferred,以保证调用接口正常

同步服务中不当的使用了noCursorTimeout的cursor。

通过慢查询定位异常业务

cursor的堆积造成了异常的内存消耗(wt cache外的内存),进而影响到了从节点producer thread的速率,从而原困了主从延迟的产生。

此前该业务经常经常出现过异常,从而原困服务不断异常与重启,每种了780k+个notimeout的cursor,而每个cursor是有额外内存的消耗,从而原困主节点内存被无效的cursor占用(此处占用的内存之前 wt cache,并且剩余的ram,所以 此时监控的wt cache的相关指标之前 正常的),有之前 每个请求除了利用wt cache外还是会产生外部ram的消耗,如connection,结果集临时存储等。此时从节点producer thread来拉取oplog的速率降低,进一步造成了主从延迟的产生。

从节点的磁盘性能不够(客户在当时并未提供io和吞吐具体情况,不过按照当时的低位qps,不应当会有磁盘性能难题,暂时排除)

而当时系统内小量的getmore成为了slow query,考虑到当时整体qps具体情况,朋友 对slow query和代码进行仔细的查看。发现了端倪:

主从延迟不稳定,有时飙升至5s

至此,你这个 难题与否完整版落下帷幕,总结一下踩的坑以及怎么能不能处理

在mongodb源码中定义了另有两个的计算法律法律依据

验证与总结

从顶端的特点朋友 不用 判断类事说说不用是正常业务场景,也之前 A或B接口触发的,回顾下整个服务体系中会对oplog.rs有没人查询的为trace oplog的场景,来源于有两个从mongodb同步数据到elasticsearch的应用。该应用会实时trace oplog 并进行同步。检查了下服务代码,每种如下:

在上述本身方案中,朋友 选泽 了方案1“归还SecondaryPreferred”来作为应急处理方案。原困如下:

前段时间笔者的客户遇到了有两个主从延迟原困的业务故障,故障的原困另有两个是较为简单易查的,有之前 将会客户环境的安全、保密性要求,监控和指标必须间接获知,信息比较片段化与迟缓。

体现了若干游标定义

类型为getmore

是针对oplog.rs的慢查询

首先从最直观的难题进行入手,观察到 db.printSlaveReplicationInfo()返回的结果和客户处集群的可视化监控显示主从延迟不稳定,会不时飙升至5s,如:

让朋友 来梳理下这次故障的前因后果。

居于local.oplog.rs的slow query

将会短时间内朋友 无法查看客户处mongodb集群的具体情况与监控指标,方案3实现周期长于前两者,故而放弃。

MongoDB的读写分离并之前 真正意义上的将读写压力完整版分离,Primary上的写最终还是以oplog的形式在从上进行了回放,读写分离的效果有限,所以 在判断集群整体压力居于合理范围内,朋友 考虑归还

在ISODate(“2018-10-24T07:00:05Z”)进行了有两个写操作a(insert/update/delete)

主从克隆qq好友好友延迟是有两个非常严重且影响业务的指标,此处显示的5s的时间在有读写分离的场景中将会不用 认为是非常影响业务的。

验证1:小量cursor原困wt cache外的ram资源紧张,进而造成主从延迟。

一般主从延迟有以下几种将会原困:

9月初朋友 的某客户反馈,部署在其私有云中的Teambition系统居于异常。该客户通过调用系统的开放API包装了一层业务向外部提供,此时有两个连续接口调用之间经常经常出现了数据一致性异常,原困包装的上层业务无法正常使用,而此时Teambition系统本身业务使用均正常。

临时应对与考量(该具体情况下快速恢复业务的选泽 )

至此,朋友 大体推断出了根因。

难题为在第二步的过程中,无法查找到第一步中”新建的任务_id”。考虑到该客户使用的是MongoDB克隆qq好友好友集架构,有之前 第两个接口的query使用了SecondaryPreferred,将会此时朋友 无法连接到数据库查看指标也无法查看多客户处该mongodb集群的监控信息,根据已有信息初步判断故障原困将会为“主从延迟”原困的数据一致性难题。

将会该集群环境的监控以及具体情况无法直接查看必须通过客户转述,你这个 过程遗漏了所以 信息也造成了所以 时间的浪费,在有将会的具体情况下,mongodb的使用者还是需用对mongodb的全面指标进行监控,魔鬼往往隐藏在细节中。

将会该上层业务重要性较高,摆在眼前 的首要具体情况是恢复该业务的可用性,综合考虑后,得出了如下的几种处理法律法律依据:

主节点上居于一些异常的慢查询,影响了从节点上producer thread拉取oplog的速率,从而原困延迟(最有将会)

看起来从节点落后了主节点25秒的时间,十分严重。有之前 将会场景的特殊性,此时落后的是有两个写操作,有之前 将会执行时间的原困,该写操作后续加快速率也完成了同步。此时的25secs对于集群来说影响甚微。

方案2需用客户包装上层业务进行修改,而客户的接口调用场景极多,故而放弃。(其实放弃该方案,有之前 需用提醒的是,在任何涉及到数据一致性要求的业务场景都需用充分考虑到异常和将会性,在业务层尽将会的规避。这也是为那先 有主从延迟的之前 Teambition系统本身并未)

集群正居于写操作极为空闲的阶段

接到反馈后朋友 与对方同步了其包装的业务逻辑,大体为:

背景

看起来该值的计算并没人那先 难题,有之前 在某类场景下,db.printSlaveReplicationInfo()的返回值(即主从延迟)并没人没人贴切。如:

处理对local库内表的操作,将会有骚操作的需求,需用明白被委托人在做那先 ,同時 将骚操作安排在隐藏节点中进行(将会此次最初朋友 的业务使用的是隐藏节点,该难题就不用直接影响到业务)且新版本不用 使用changestream来满足类事trace oplog的需求。

Connections连接数稳定,并无暴增暴减

调用接口B(可简单认为insert了一根数据b,但在insert之前 检查了接口A返回的数据a的_id)

为了释放cursor朋友 将节点实例重启并关闭同步服务,持续观察后,确认主从延迟具体情况不再经常经常出现恢复正常。将SecondaryPreferred重新启用,业务也一切正常。

使用cursor之前 本身使用noCursorTimeout能力,为cursor设置合理的timeout,由应用来控制timeout后的重试机制。以此来保证cursor的合理利用。

Resident Memory稳定,且整体eviction具体情况良好