赞
踩
mongodb内核、wiredtiger存储引擎、rocksdb存储引擎相关源码分析详见(后续持续更新):
https://github.com/y123456yz/reading-and-annotate-mongodb-3.6.1
线上某集群峰值TPS超过100万/秒左右(主要为写流量,读流量很低),峰值tps几乎已经到达集群上限,同时平均时延也超过100ms,随着读写流量的进一步增加,时延抖动严重影响业务可用性。该集群采用mongodb天然的分片模式架构,数据均衡的分布于各个分片中,添加片键启用分片功能后实现完美的负载均衡。集群每个节点流量监控如下图所示:
从上图可以看出集群流量比较大,峰值已经突破120万/秒,其中delete过期删除的流量不算在总流量里面(delete由主触发删除,但是主上面不会显示,只会在从节点拉取oplog的时候显示)。如果算上主节点的delete流量,总tps超过150万/秒。
在不增加服务器资源的情况下,首先做了如下软件层面的优化,并取得了理想的数倍性能提升:
该集群总文档近百亿条,每条文档记录默认保存三天,业务随机散列数据到三天后任意时间点随机过期淘汰。由于文档数目很多,白天平峰监控可以发现从节点经常有大量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含义
1. 在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操作,主节点没有?
原因是过期索引只在master主节点触发,触发后主节点会直接删除调用对应wiredtiger存储引擎接口做删除操作,不会走正常的客户端链接处理流程,因此主节点上看不到delete统计。
主节点过期delete后会生存对于的delete oplog信息,从节点通过拉取主节点oplog然后模拟对于client回放,这样就保证了主数据删除的同时从数据也得以删除,保证数据最终一致性。从节点模拟client回放过程将会走正常的client链接过程,因此会记录delete count统计,详见如下代码:
官方参考如下: https://docs.mongodb.com/manual/tutorial/expire-data/
由于集群tps高,同时整点有大量推送,因此整点并发
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。