连环触发!MongoDB核心集群雪崩故障背后竟是……

作者介绍
杨亚洲 , 前滴滴出行技术专家 , 现任OPPO文档数据库MongoDB负责人 , 负责OPPO千万级峰值TPS/十万亿级数据量文档数据库MongoDB内核研发及运维工作 , 一直专注于分布式缓存、高性能服务端、数据库、中间件等相关研发 。
一、问题背景
某核心JAVA长连接服务使用MongoDB作为主要存储 , 客户端数百台机器连接同一MongoDB集群 , 短期内出现多次性能抖动问题 , 此外 , 还出现一次“雪崩”故障 , 同时流量瞬间跌零 , 无法自动恢复 。 本文分析这两次故障的根本原因 , 包括客户端配置使用不合理、MongoDB内核链接认证不合理、代理配置不全等一系列问题 , 最终经过多方努力确定问题根源 。
该集群有十来个业务接口访问 , 每个接口部署在数十台业务服务器上面 , 访问该MongoDB机器的客户端总数超过数百台 , 部分请求一次拉取数十行甚至百余行数据 。
该集群为2机房同城多活集群(选举节不消耗太多资源 , 异地的第三机房来部署选举节点) , 架构图如下:
连环触发!MongoDB核心集群雪崩故障背后竟是……文章插图
【连环触发!MongoDB核心集群雪崩故障背后竟是……】从上图可以看出 , 为了实现多活 , 在每个机房都部署有对应代理 , 对应机房客户端链接对应机房的mongos代理 , 每个机房多个代理 。 代理层部署IP:PORT地址列表(注意:不是真实IP地址)如下:
A机房代理地址列表:1.1.1.1:111,2.2.2.2:1111,3.3.3.3:1111
B机房代理地址列表:4.4.4.4:1111,4.4.4.4:2222
A机房三个代理部署在三台不同物理机 , B机房2个代理部署在同一台物理机 。 此外 , A机房和B机房为同城机房 , 跨机房访问时延可以忽略 。
集群存储层和config server都采用同样的架构:A机房(1主节点+1从节点) + B机房(2从节点)+C机房(1个选举节点arbiter) , 即2(数据节点)+2(数据节点)+1(选举节点)模式 。
该机房多活架构可以保证任一机房挂了 , 对另一机房的业务无影响 , 具体机房多活原理如下:

  1. 如果A机房挂掉 , 由于代理是无状态节点 , A机房挂掉不会影响B机房的代理 。
  2. 如果A机房挂掉 , 同时主节点在A机房 , 这时候B机房的2个数据节点和C机房的选举节点一共三个节点 , 可以保证新选举需要大于一半以上节点这个条件 , 于是B机房的数据节点会在短时间内选举出一个新的主节点 , 这样整个存储层访问不受任何影响 。
本文重点分析如下6个疑问点:
  1. 为什么突发流量业务会抖动?
  2. 为什么数据节点没有任何慢日志 , 但是代理负载缺100%?
  3. 为何mongos代理引起数小时的“雪崩” , 并且长时间不可恢复?
  4. 为何一个机房代理抖动 , 对应机房业务切到另一个机房后 , 还是抖动?
  5. 为何异常时候抓包分析 , 客户端频繁建链断链 , 并且同一个链接建链到断链间隔很短?
  6. 理论上代理就是七层转发 , 消耗资源更少 , 相比mongod存储应该更快 , 为何mongod存储节点无任何抖动 , mongos代理却有抖动?
二、故障过程
1、业务偶尔流量高峰 , 业务抖动?
该集群一段时间内有多次短暂的抖动 , 当A机房客户端抖动后 , 发现A机房对应代理负载很高 , 于是切换A机房访问B机房代理 , 但是切换后B机房代理同样抖动 , 也就是多活切换没有作用 , 具体过程分析如下 。
1)存储节点慢日志分析
首先 , 分析该集群所有mongod存储节点系统CPU、MEM、IO、load等监控信息 , 发现一切正常 , 于是分析每个mongod节点慢日志(由于该集群对时延敏感 , 因此慢日志调整为30ms) , 分析结果如下:
连环触发!MongoDB核心集群雪崩故障背后竟是……文章插图
连环触发!MongoDB核心集群雪崩故障背后竟是……文章插图
连环触发!MongoDB核心集群雪崩故障背后竟是……文章插图
从上图可以看出 , 存储节点在业务抖动的时候没有任何慢日志 , 因此可以判断存储节点一切正常 , 业务抖动和mongod存储节点无关 。
2) mongos代理分析
存储节点没有任何问题 , 因此开始排查mongos代理节点 。 由于历史原因 , 该集群部署在其他平台 , 该平台对QPS、时延等监控不是很全 , 造成早期抖动的时候监控没有及时发现 。 抖动后 , 迁移该平台集群到oppo自研的新管控平台 , 新平台有详细的监控信息 , 迁移后QPS监控曲线如下:
连环触发!MongoDB核心集群雪崩故障背后竟是……文章插图