mongodb 百万_OPPO百万级高并发MongoDB集群性能数十倍提升优化实践(上)

1. 背景

线上某集群峰值TPS超过100万/秒左右(主要为写流量,读流量很低),峰值tps几乎已经到达集群上限,同时平均时延也超过100ms,随着读写流量的进一步增加,时延抖动严重影响业务可用性。该集群采用mongodb天然的分片模式架构,数据均衡的分布于各个分片中,添加片键启用分片功能后实现完美的负载均衡。集群每个节点流量监控如下图所示:

从上图可以看出集群流量比较大,峰值已经突破120万/秒,其中delete过期删除的流量不算在总流量里面(delete由主触发删除,但是主上面不会显示,只会在从节点拉取oplog的时候显示)。如果算上主节点的delete流量,总tps超过150万/秒。

2. 软件优化

在不增加服务器资源的情况下,首先做了如下软件层面的优化,并取得了理想的数倍性能提升:业务层面优化

Mongodb配置优化

存储引擎优化

2.1 业务层面优化

该集群总文档近百亿条,每条文档记录默认保存三天,业务随机散列数据到三天后任意时间点随机过期淘汰。由于文档数目很多,白天平峰监控可以发现从节点经常有大量delete操作,甚至部分时间点delete删除操作数已经超过了业务方读写流量,因此考虑把delete过期操作放入夜间进行,过期索引添加方法如下:

Db.collection.createIndex( { “expireAt”: 1 }, { expireAfterSeconds: 0 } )

上面的过期索引中 expireAfterSeconds=0,代表 collection 集合中的文档的过期时间点在 expireAt 时间点过期,例如:

db.collection.insert ({

//表示该文档在夜间凌晨1点这个时间点将会被过期删除

“expireAt”: new Date(‘July 22, 2019 01:00:00’),

“logEvent”: 2,

“logMessage”: “Success!”

})

通过随机散列expireAt在三天后的凌晨任意时间点,即可规避白天高峰期触发过期索引引入的集群大量delete,从而降低了高峰期集群负载,最终减少业务平均时延及抖动。

Delete 过期 Tips1: expireAfterSeconds 含义在expireAt指定的绝对时间点过期,也就是12.22日凌晨2:01过期

Db.collection.createIndex( { “expireAt”: 1}, { expireAfterSeconds: 0 })

db.log_events.insert( { “expireAt”: new Date(Dec 22, 2019 02:01:00′),”logEvent”: 2,”logMessage”: “Success!”})在expireAt指定的时间往后推迟expireAfterSeconds秒过期,也就是当前时间往后推迟60秒过期

db.log_events.insert( {“createdAt”: new Date(),”logEvent”: 2,”logMessage”: “Success!”} )

Db.collection.createIndex( { “expireAt”: 1 }, { expireAfterSeconds: 60 } )

Delete过期Tips2:为何mongostat只能监控到从节点有delete操作,主节点没有/p>

原因是过期索引只在master主节点触发,触发后主节点会直接删除调用对应wiredtiger存储引擎接口做删除操作,不会走正常的客户端链接处理流程,因此主节点上看不到delete统计。

主节点过期delete后会生存对于的delete oplog信息,从节点通过拉取主节点oplog然后模拟对于client回放,这样就保证了主数据删除的同时从数据也得以删除,保证数据最终一致性。从节点模拟client回放过程将会走正常的client链接过程,因此会记录delete count统计。

2.2 Mongodb配置优化( 络IO复用, 络IO和磁盘IO做分离)

由于集群tps高,同时整点有大量推送,因此整点并发会更高,mongodb默认的一个请求一个线程这种模式将会严重影响系统负载,该默认配置不适合高并发的读写应用场景。官方介绍如下:

优化配置的load

优化配置后的慢日志数(5222):

从上图可以看出, 络IO复用后时延降低了1-2倍。

2.3 wiredtiger存储引擎优化

从上一节可以看出平均时延从200ms降低到了平均80ms左右,很显然平均时延还是很高,如何进一步提升性能降低时延续分析集群,我们发现磁盘IO一会儿为0,一会儿持续性100%,并且有跌0现象,现象如下:

总体IO负载曲线如下:

于是查看mongod.conf配置文件,发现配置文件中配置的cacheSizeGB: 110G,可以看出,存储引擎中KV总量几乎已经达到110G,按照5%脏页开始刷盘的比例,峰值情况下cachesSize设置得越大,里面得脏数据就会越多,而磁盘IO能力跟不上脏数据得产生速度,这种情况很可能就是造成磁盘I/O瓶颈写满,并引起I/O跌0的原因。

此外,查看该机器的内存,可以看到内存总大小为190G,其中已经使用110G左右,几乎是mongod的存储引起占用,这样会造成内核态的page cache减少,大量写入的时候内核cache不足就会引起磁盘缺页中断。

从上面的IO负载图可以看出,之前的IO一会儿为0%,一会儿100%现象有所缓解,总结如下图所示:

从上图可以看出,存储引擎优化后时间延迟进一步降低并趋于平稳,从平均80ms到平均20ms左右,但是还是不完美,有抖动。

3. 服务器系统磁盘IO问题解决

3.1 服务器IO硬件问题背景

如第3节所述,当wiredtiger大量淘汰数据后,发现只要每秒磁盘写入量超过500M/s,接下来的几秒钟内util就会持续100%,w/s几乎跌0,于是开始怀疑磁盘硬件存在缺陷。

从上图可以看出磁盘为nvMe的ssd盘,查看相关数据可以看出该盘IO性能很好,支持每秒2G写入,iops能达到2.5W/S,而我们线上的盘只能每秒写入最多500M。

3.2 服务器IO硬件问题解决后性能对比

于是考虑把该分片集群的主节点全部迁移到另一款服务器,该服务器也是ssd盘,io性能达到2G/s写入(注意:只迁移了主节点,从节点还是在之前的IO-500M/s的服务器)。迁移完成后,发现性能得到了进一步提升,时延迟降低到2-4ms/s,三个不同业务层面看到的时延监控如下图所示:

相关资源:倍速软件,可以加速观看过程_倍速播放学习-图像处理工具类资源…

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2020年11月18日
下一篇 2020年11月18日

相关推荐