大发棋牌大发棋牌技巧技巧 关于 作者
前滴滴出行大发棋牌大发棋牌技巧技巧 技术 专家,现任OPPO文档数据库mongodb负责人,负责oppo千万级峰值TPS/十万亿级数据量文档数据库mongodb研发和运维工作,一直专注于分布式缓存、高性能大发棋牌大发棋牌技巧技巧 服务 端、数据库、中间件等相关研发。后续持续分享《MongoDB内核源码设计、性能大发棋牌大发棋牌技巧技巧 优化 、最佳运维实践》,Github账号大发棋牌大发棋牌技巧技巧 地址 :http://github.com/y123456yz

1.前言
温馨提示:在进行本下篇大发棋牌大发棋牌技巧技巧 优化 文章阅读前,可以提前了解下《百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧 优化 实践(上篇)》()的问题背景及大发棋牌大发棋牌技巧技巧 优化 大发棋牌技巧方法 ,这样可以更好的了解和学习本篇性能大发棋牌大发棋牌技巧技巧 优化 下篇的内容。
上篇大发棋牌大发棋牌技巧技巧 地址 :http://wnfkyy.com/14951246/2540109

2.背景
线上某集群峰值TPS超过100万/秒左右(主要为写流量,读流量很低,读写流量做了主从读写分离,读流量走从节点,qps数百上千),峰值tps几乎已经到达集群上限,同时平均时延也超过100ms,随着读写流量的进一步增加,时延抖动严重影响业务可用性。该集群采用mongodb天然的分片模式架构,数据均衡的分布于各个分片中,添加片键启用分片功能后实现完美的负载均衡。集群每个节点流量监控如下图所示:
百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)
百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)
从上图可以看出集群流量比较大,峰值已经突破120万/秒,其中delete过期大发棋牌大发棋牌技巧技巧 删除 的流量不算在总流量里面(delete由主触发大发棋牌大发棋牌技巧技巧 删除 ,但是主上面不会显示,只会在从节点拉取oplog的时候显示)。如果算上主节点的delete流量,总tps超过150万/秒。
在《百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧 优化 实践(上篇)》中,大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 通过业务大发棋牌大发棋牌技巧技巧 优化 、mongodb大发棋牌大发棋牌技巧技巧 服务 层配置大发棋牌大发棋牌技巧技巧 优化 、wiredtiger存储引擎层大发棋牌大发棋牌技巧技巧 优化 及硬件IO大发棋牌大发棋牌技巧技巧 优化 后,客户端总体时延从几百ms迟控制到了2-5ms左右,总体性能有了很大的提升,但是当有超大流量写冲击的时候,会有几十ms时延抖动,几个不同接口的时延如下图所示:
百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)
3.硬件问题回顾及遗留问题
在《上篇》文章中,大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 通过定位nvme ssd硬件的IO问题后,和厂商一起分析后发现IO问题是因为操作系统版本不对引起,于是开始对线上的主从mongod实例的大发棋牌大发棋牌技巧技巧 服务 器硬件进行升级,升级后开始替换线上该集群的实例。具体操作过程如下:
1.为了验证IO升级后的机器,大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 替换一个分片的从节点为升级后的大发棋牌大发棋牌技巧技巧 服务 器(IO问题得以解决,IO能力从之前的500M/s写入达到了近2G/s,大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 称IO升级后的大发棋牌大发棋牌技巧技巧 服务 器为高IO大发棋牌大发棋牌技巧技巧 服务 器,未升级的大发棋牌大发棋牌技巧技巧 服务 器为低IO大发棋牌大发棋牌技巧技巧 服务 器),替换后通过iostat可以看到该从节点的IO 100%问题得到了很大程度的缓解,不会出现持续性IO跌0问题。
2.第一步上面的大发棋牌大发棋牌技巧技巧 服务 器跑了一周后,大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 确定升级后的高IO大发棋牌大发棋牌技巧技巧 服务 器运行稳定,为了谨慎起见,大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 虽然确定该高IO大发棋牌大发棋牌技巧技巧 服务 器在从节点运行没有问题,但是大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 需要进一步在主节点验证是否文档,于是大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 做了一次主从切换,该高IO大发棋牌大发棋牌技巧技巧 服务 器变为主节点运行,也就是集群中某个分片的主节点为高IO大发棋牌大发棋牌技巧技巧 服务 器,但是从节点还是低IO大发棋牌大发棋牌技巧技巧 服务 器。
3.当高IO大发棋牌大发棋牌技巧技巧 服务 器在某个分片的主节点跑了数周后,大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 确定高IO大发棋牌大发棋牌技巧技巧 服务 器在主节点运行正常,于是大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 得下结论: 升级后的大发棋牌大发棋牌技巧技巧 服务 器运行稳定。
4.确定高IO大发棋牌大发棋牌技巧技巧 服务 器没问题后,大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 开始批量替换mongod实例到该大发棋牌大发棋牌技巧技巧 服务 器。为了保险起见,毕竟只验证了一台高IO大发棋牌大发棋牌技巧技巧 服务 器在主从运行都没问题,于是大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 考虑只把整个集群的主节点替换为高IO大发棋牌大发棋牌技巧技巧 服务 器(因为当时大发棋牌大发棋牌技巧技巧 我 认为客户端都是用的默认配置,数据写到主节点就会返回OK,虽然从节点IO慢,但是还是可以追上oplog速度的,这样客户端时延就会很好的得到控制)。

为了谨慎保险起见,通过上面的硬件替换升级过程,大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 只替换了所有分片的主节点,提后前后架构发生了变化,原有集群硬件架构如下图所示:
百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)
所有分片主节点硬件升级后的架构图如下图所示:
百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)
从上图可知,新的集群架构,主从节点大发棋牌大发棋牌技巧技巧 服务 器IO能力有比较大的差距。最开始大发棋牌大发棋牌技巧技巧 我 认为业务方默认没有设置WriteConncern,也就是默认写入到Primary就向客户端发送确认,因此不会影响业务写入。
所有分片主节点升级为高IO大发棋牌大发棋牌技巧技巧 服务 器后,多个业务接口的时间访问延迟降到了平均2-4ms左右,但是在超大流量冲击的时候,还是有几十ms的尖刺,大发棋牌大发棋牌技巧技巧 我 选取一个接口的时延为例,如下图所示:
百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇) 从上图可以看出,特别是在大流量冲击的时间点,尖刺越明显。
4.主节点硬件升级后大发棋牌大发棋牌技巧技巧 优化
4.1 readConcern配置大发棋牌大发棋牌技巧技巧 优化
在上一节,大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 替换了分片的所有主节点为高IO大发棋牌大发棋牌技巧技巧 服务 器,从节点还是以前未升级的低IO大发棋牌大发棋牌技巧技巧 服务 器。由于业务方默认没有设置WriteConncern,因此大发棋牌大发棋牌技巧技巧 我 认为客户端写到主成功就会返回客户端OK,即使从大发棋牌大发棋牌技巧技巧 服务 器性能差也不会影响客户端写主。
在升级主大发棋牌大发棋牌技巧技巧 服务 器后,大发棋牌大发棋牌技巧技巧 我 继续大发棋牌大发棋牌技巧技巧 优化 存储引擎把eviction_dirty_trigger:25%调整到了30%。
由于在超大流量的高并发冲击,会从平峰期的几十万TPS瞬间飙升到百万级别,而且该毛刺几乎每天都会出现两三次,比较容易复现。于是提前部署好mongostat监控所有实例,同时在每个大发棋牌大发棋牌技巧技巧 服务 器上用Iostat监控实时的IO状况,同时编写脚本实时采集db.serverstatus()、db.printSlaveReplicationInfo()、db.printReplicationInfo()等集群重要信息。
当某个时间点监控出现毛刺后,于是开始分析mongostat,大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 发现一个问题,即使在平峰期,脏数据比例也会持续增长到阀值(30%),大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 知道当脏数据比例超过eviction_dirty_trigger:30%阀值,用户线程就会进行evict淘汰,这样用户线程就会阻塞直到腾出内存空间,因此淘汰刷盘过程很慢。分析平峰期毛刺时间点对应的mongostat监控,发现如下情况:百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇) 从上图可以看出,集群TPS才40-50万左右的时候某个分片的主节点出现了脏数据达到eviction_dirty_trigger:30%阀值,于是整个集群访问时延就会瞬间增加,原因是一个分片的用户线程需要刷盘,导致这个分片的访问时延上升(实际上其他分片的访问时延还是正常的),最终把整体平均时延拉上去了。
为什么普通平峰期也会有抖动?这很明显不科学。
于是获取出问题的主节点的一些监控信息,得出以下结论:
1.IO正常,IO不是瓶颈。
2.分析抖动的时候的系统top负载,负载正常。
3.该分片的TPS才4万左右,显然没到到分片峰值。
4.db.printSlaveReplicationInfo()看到主从延迟较高。
当客户端时延监控发现时间延迟尖刺后,大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 发现主节点所有现象一切正常,系统负载、IO、TPS等都没有到达瓶颈,但是有一个唯一的异常,就是主从同步延迟持续性增加,如下图所示:百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)
同时对应低IO大发棋牌大发棋牌技巧技巧 服务 器的从节点上面的io状况如下图:
百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)
从节点的IO性能一塌乌涂,这也正式主从延迟增加的根源。

从上图可以看出在时延尖刺的同样时间点,主从延迟超大。于是怀疑时延尖刺可能和从节点拉取Oplog速度有关系,于是把整个mongostat、iostat、top、db.printSlaveReplicationInfo()、db.serverstatus()等监控持续跑了两天,记录下了两天内的一些核心系统和mongo监控指标。
两天后,对着客户端时延尖刺时间点分析对应监控数据,发现一个共同的现象,尖刺出现时间点和脏数据eviction_dirty_trigger超过阀值时间点一致,同时主从延迟在这个时间点都有很大的延迟。
到这里,大发棋牌大发棋牌技巧技巧
我
越来越怀疑问题和从节点拉取oplog速度有关。之前认为业务方默认没有设置WriteConncern,也就是默认写入到Primary就向客户端发送确认,可能应答客户端前还有其他流程会影响写入。于是查看mongodb-3.6的Production Notes,从中发现了如下信息:
    ![](http://s4.51cto.com/images/blog/202010/16/18cd6dcd31cdf0a29b44ca3da1be4124.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)    从Production Notes可以看出,mongodb-3.6默认启用了 read concern "majority"功能,于是怀疑抖动可能和该功能有关。为了避免藏独,mongodb增加了该功能,启用该功能后,mongodb为了确保带有带有参数readConcern("Majority")的客户端读取到的数据确实是同步到大多数实例的数据,因此mongodb必须在内存中借助snapshot 及主从通信来维护大发棋牌大发棋牌技巧技巧
更多
的版本信息,这就增加了wiredtiger存储引擎对内存的需求。由于从节点是低IO大发棋牌大发棋牌技巧技巧
服务
器,很容易造成阻塞,这样拉取oplog的速度就会跟不上进度,造成主节点消耗大量的内存来维护快照信息,这样就会导致大量的内存消耗,最终导致脏数据瞬间剧增,很快达到eviction_dirty_trigger阀值,业务也因此抖动。
说一个小插曲,因为mongodb-3.6默认开启enableMajorityReadConcern功能,大发棋牌大发棋牌技巧技巧
大发棋牌大发棋牌技巧技巧
我
们
在这个过程中出现过一次严重的集群故障,业务流量有段时间突然暴涨,造成时延持续性达到几千ms,现象如下:![](http://s4.51cto.com/images/blog/202010/16/840d83e3ebe24fda5732dc4920e4eaf7.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
    该问题的根源也是因为enableMajorityReadConcern功能引起,由于从节点严重落后主节点,导致主节点为了维护各种snapshot快照,消耗大量内存,同时从节点和主节点的oplog延后,导致主节点维护了大发棋牌大发棋牌技巧技巧
更多
的内存版本,脏数据比例持续性增长,直到从节点追上oplog。由于大发棋牌大发棋牌技巧技巧
大发棋牌大发棋牌技巧技巧
我
们
的业务不需要readConcert功能,因此大发棋牌大发棋牌技巧技巧
大发棋牌大发棋牌技巧技巧
我
们
考虑禁用该功能(配置文件增加配置replication.enableMajorityReadConcern=false)。
鉴于篇幅,enableMajorityReadConcern及主从硬件IO能力不足引起的严重业务故障,本篇不做详细的分析,后期会写一篇专门的《百万计高并发mongodb集群性能大发棋牌大发棋牌技巧技巧
优化
采坑记》中做分享,除了ReadConcern采坑,还有其他好几个核心采坑点,敬请关注。

此外,后续会专门写一篇ReadConcern的原理及代码实现分析文章,敬请关注。

4.2 替换从节点大发棋牌大发棋牌技巧技巧 服务 器为升级后的高IO大发棋牌大发棋牌技巧技巧 服务 器
除了通过replication.enableMajorityReadConcern=false在配置文件中禁用ReadConcern Majority功能,大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 继续把所有分片的从节点由之前的低IO大发棋牌大发棋牌技巧技巧 服务 器替换为升级后的高IO大发棋牌大发棋牌技巧技巧 服务 器,升级后所有主从硬件资源性能完全一样,升级后集群分片架构如下图所示:百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)通过禁用功能,并统一主从大发棋牌大发棋牌技巧技巧 服务 器硬件资源后,查看有抖动的一个接口的时间延迟,如下图所示:百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)从上图可以看出,通过MajorityReadConcern功能并且替把所有从节点的低IO大发棋牌大发棋牌技巧技巧 服务 器做系统升级后,业务时间延迟抖动的峰值进一步降低了,从之前第3节中的峰值80ms降低到了现在的峰值40ms左右。
此外,4.1节提到的脏数据持续性突破eviction_dirty_trigger阀值引起客户端时延飙涨到几千ms的问题得以彻底解决。

4.3 继续大发棋牌大发棋牌技巧技巧 优化 调整存储引起参数
通过前面的条大发棋牌大发棋牌技巧技巧 优化 ,大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 发现有一个业务接口还是偶尔有40ms时延尖刺,分析发现主要是eviction_dirty_trigger达到了大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 配置的阀值,业务线程开始淘汰page cache,这样就造成业务线程很慢,最终导致平均时延尖刺。
为了进一步减缓时延尖刺,大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 继续在之前基础上对存储引擎调优,调整后配置如下:
eviction_target: 75%
eviction_trigger:97%
eviction_dirty_target: %3
eviction_dirty_trigger:30%
evict.threads_min:12
evict.threads_max:18
checkpoint=(wait=20,log_size=1GB)
经过此轮的存储引擎调优后,该业务的核心接口时延进一步好转,时延尖刺相比之前有了进一步的改善,时延最大尖刺时间从前面的40ms降低到了30ms,同时尖刺出现的频率明显降低了,如下图所示:百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)从此图可以看出,在个别时间点还是有一次时延尖刺,对照该尖刺的时间点分析提前部署好的mongostat和iostat监控,得到如下信息:百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)从上图可以看出,在峰值TPS百万级别的时候,部分节点evict淘汰速率已经跟不上写入速度,因此出现了用户线程刷盘的情况。
但是,很奇怪的是,在这个时间点分析对应机器的系统负载、io状况、内存状况等,发现系统负载、比较正常,但是对应大发棋牌大发棋牌技巧技巧 服务 器IO偏高,如下图所示:百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇) 同时分析对应大发棋牌大发棋牌技巧技巧 服务 器对应时间点的慢日志,大发棋牌大发棋牌技巧技巧 大发棋牌大发棋牌技巧技巧 我 们 发现尖刺出现时间的的慢日志统计如下:百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)分析非时延尖刺时间点,对应慢日志统计如下:百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)分析两个时间点慢日志可以看出,慢日志出现的条数和时间延迟尖刺出现的时间点一致,也就是IO负载很高的时候。
通过上面的分析可以看出,当IO比较高(util超过50%)的时候,慢日志和时延都会增加,他们之间成正比关系。

5.总结
通过大发棋牌大发棋牌技巧技巧 软件 层面(mongodb大发棋牌大发棋牌技巧技巧 服务 配置、业务大发棋牌大发棋牌技巧技巧 优化 、存储引擎大发棋牌大发棋牌技巧技巧 优化 )及硬件大发棋牌大发棋牌技巧技巧 优化 (升级操作系统)后,该大流量集群的核心接口时延从最初的平均成百上千ms降低到了现在的平均1-2ms,性能提升比较可观,整体时延性能提升数十倍。
大发棋牌大发棋牌技巧技巧 优化 前主要接口时延:百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)在不增加物理机器的基础上,经过一系列的大发棋牌大发棋牌技巧技巧 优化 措施,最终业务方主要接口时延控制到了几ms,如下图所示:百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)百万级高并发mongodb集群性能数十倍提升大发棋牌大发棋牌技巧技巧
优化
实践(下篇)