1. 首页
  2. IT资讯

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

“u003Ch1 class=”pgc-h-arrow-right”u003E背景u003Cu002Fh1u003Eu003Cpu003E线上某集群峰值TPS超过100万u002F秒左右(主要为写流量,读流量很低),峰值tps几乎已经到达集群上限,同时平均时延也超过100ms,随着读写流量的进一步增加,时延抖动严重影响业务可用性。该集群采用mongodb天然的分片模式架构,数据均衡的分布于各个分片中,添加片键启用分片功能后实现完美的负载均衡。集群每个节点流量监控如下图所示:u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002F646a94f7a81c48a8ba3e37ba65764922″ img_width=”830″ img_height=”516″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp9.pstatp.comu002Flargeu002Fpgc-imageu002Fff8b3d4807c44a4bbe5ba51ab8a89195″ img_width=”831″ img_height=”328″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E从上图可以看出集群流量比较大,峰值已经突破120万u002F秒,其中delete过期删除的流量不算在总流量里面(delete由主触发删除,但是主上面不会显示,只会在从节点拉取oplog的时候显示)。如果算上主节点的delete流量,总tps超过150万u002F秒。u003Cu002Fpu003Eu003Ch1 class=”pgc-h-arrow-right”u003E软件优化u003Cu002Fh1u003Eu003Cpu003E在不增加服务器资源的情况下,首先做了如下软件层面的优化,并取得了理想的数倍性能提升:u003Cu002Fpu003Eu003Col start=”1″u003Eu003Cliu003E业务层面优化u003Cu002Fliu003Eu003Cliu003EMongodb配置优化u003Cu002Fliu003Eu003Cliu003E存储引擎优化u003Cu002Fliu003Eu003Cu002Folu003Eu003Cpu003Eu003Cstrongu003E2.1 业务层面优化u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E该集群总文档近百亿条,每条文档记录默认保存三天,业务随机散列数据到三天后任意时间点随机过期淘汰。由于文档数目很多,白天平峰监控可以发现从节点经常有大量delete操作,甚至部分时间点delete删除操作数已经超过了业务方读写流量,因此考虑把delete过期操作放入夜间进行,过期索引添加方法如下:u003Cu002Fpu003Eu003Cpu003EDb.collection.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )u003Cu002Fpu003Eu003Cpu003E上面的过期索引中expireAfterSeconds=0,代表collection集合中的文档的过期时间点在expireAt时间点过期,例如:u003Cu002Fpu003Eu003Cblockquoteu003Eu003Cpu003Eu003Cbru002Fu003E db.collection.insert( {u003Cu002Fpu003Eu003Cpu003E u002Fu002F表示该文档在夜间凌晨1点这个时间点将会被过期删除u003Cu002Fpu003Eu003Cpu003E "expireAt": new Date('July 22, 2019 01:00:00'), u003Cu002Fpu003Eu003Cpu003E "logEvent": 2,u003Cu002Fpu003Eu003Cpu003E "logMessage": "Success!"u003Cu002Fpu003Eu003Cpu003E } )u003Cu002Fpu003Eu003Cu002Fblockquoteu003Eu003Cpu003E通过随机散列expireAt在三天后的凌晨任意时间点,即可规避白天高峰期触发过期索引引入的集群大量delete,从而降低了高峰期集群负载,最终减少业务平均时延及抖动。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003EDelete过期Tips1: expireAfterSeconds含义u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E1. 在u003Cu002Fstrongu003EexpireAt指定的绝对时间点过期,也就是12.22日凌晨2:01过期u003Cu002Fpu003Eu003Cpu003EDb.collection.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )u003Cu002Fpu003Eu003Cpu003Edb.log_events.insert( { "expireAt": new Date(Dec 22, 2019 02:01:00'),"logEvent": 2,"logMessage": "Success!"})u003Cu002Fpu003Eu003Col start=”1″u003Eu003Cliu003Eu003Cstrongu003E在u003Cu002Fstrongu003EexpireAt指定的时间往后推迟expireAfterSeconds秒过期,也就是当前时间往后推迟60秒过期u003Cu002Fliu003Eu003Cu002Folu003Eu003Cpu003E db.log_events.insert( {"createdAt": new Date(),"logEvent": 2,"logMessage": "Success!"} )u003Cu002Fpu003Eu003Cpu003EDb.collection.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 60 } )u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003EDelete过期Tips2: 为何mongostat只能监控到从节点有delete操作,主节点没有?u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E原因是过期索引只在master主节点触发,触发后主节点会直接删除调用对应wiredtiger存储引擎接口做删除操作,不会走正常的客户端链接处理流程,因此主节点上看不到delete统计。u003Cu002Fpu003Eu003Cpu003E主节点过期delete后会生存对于的delete oplog信息,从节点通过拉取主节点oplog然后模拟对于client回放,这样就保证了主数据删除的同时从数据也得以删除,保证数据最终一致性。从节点模拟client回放过程将会走正常的client链接过程,因此会记录delete count统计,详见如下代码:u003Cu002Fpu003Eu003Cpu003E官方参考如下: u003Cuu003Ehttps:u002Fu002Fdocs.mongodb.comu002Fmanualu002Ftutorialu002Fexpire-datau002Fu003Cu002Fuu003Eu003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E2.2 Mongodb配置优化(网络IO复用,网络IO和磁盘IO做分离)u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E由于集群tps高,同时整点有大量推送,因此整点并发会更高,mongodb默认的一个请求一个线程这种模式将会严重影响系统负载,该默认配置不适合高并发的读写应用场景。官方介绍如下:u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp3.pstatp.comu002Flargeu002Fpgc-imageu002Fb9fb2a95a5b442118a17e78ecdc72caf” img_width=”589″ img_height=”374″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E u003Cstrongu003E2.2.1 Mongodb内部网络线程模型实现原理u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003Emongodb默认网络模型架构是一个客户端链接,mongodb会创建一个线程处理该链接fd的所有读写请求及磁盘IO操作。u003Cu002Fpu003Eu003Cpu003EMongodb默认网络线程模型不适合高并发读写原因如下:u003Cu002Fpu003Eu003Cpu003E1. 在高并发的情况下,瞬间就会创建大量的线程,例如线上的这个集群,连接数会瞬间增加到1万左右,也就是操作系统需要瞬间创建1万个线程,这样系统load负载就会很高。u003Cu002Fpu003Eu003Cpu003E2. 此外,当链接请求处理完,进入流量低峰期的时候,客户端连接池回收链接,这时候mongodb服务端就需要销毁线程,这样进一步加剧了系统负载,同时进一步增加了数据库的抖动,特别是在PHP这种短链接业务中更加明显,频繁的创建线程销毁线程造成系统高负债。u003Cu002Fpu003Eu003Cpu003E 3. 一个链接一个线程,该线程除了负责网络收发外,还负责写数据到存储引擎,整个网络Iu002FO处理和磁盘Iu002FO处理都由同一个线程负责,本身架构设计就是一个缺陷。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E2.2.2 网络线程模型优化方法u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E 为了适应高并发的读写场景,mongodb-3.6开始引入serviceExecutor: adaptive配置,该配置根据请求数动态调整网络线程数,并尽量做到网络IO复用来降低线程创建消耗引起的系统高负载问题。此外,加上serviceExecutor: adaptive配置后,借助boost:asio网络模块实现网络IO复用,同时实现网络IO和磁盘IO分离。这样高并发情况下,通过网络链接IO复用和mongodb的锁操作来控制磁盘IO访问线程数,最终降低了大量线程创建和消耗带来的高系统负载,最终通过该方式提升高并发读写性能。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E2.2.3 网络线程模型优化前后性能对比u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E在该大流量集群中增加serviceExecutor: adaptive配置实现网络IO复用及网络IO与磁盘IO做分离后,该大流量集群时延大幅度降低,同时系统负载和慢日志也减少很多,具体如下:u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E2.2.3.1 优化前后系统负载对比u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E验证方式:u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Col start=”1″u003Eu003Cliu003E该集群有多个分片,其中一个分片配置优化后的主节点和同一时刻未优化配置的主节点load负载比较:u003Cbru002Fu003E u003Cstrongu003E未优化配置的loadu003Cu002Fstrongu003Eu003Cu002Fliu003Eu003Cu002Folu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002F3cf453dd31de42e09f5b7344bdf11bd8″ img_width=”831″ img_height=”288″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003Eu003Cstrongu003E优化配置的loadu003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp9.pstatp.comu002Flargeu002Fpgc-imageu002F99d25b0bff4340eab2687bbc3da71e68″ img_width=”681″ img_height=”476″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003Eu003Cstrongu003E2.2.3.2 优化前后慢日志对比u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E验证方式:u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E该集群有多个分片,其中一个分片配置优化后的主节点和同一时刻未优化配置的主节点慢日志数比较:u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E同一时间的慢日志数统计:u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E未优化配置的慢日志数u003Cstrongu003E(19621)u003Cu002Fstrongu003E:u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp3.pstatp.comu002Flargeu002Fpgc-imageu002F48859fecda9a4f6ba82ebd7dc201e8a9″ img_width=”831″ img_height=”69″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E优化配置后的慢日志数u003Cstrongu003E(5222):u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp9.pstatp.comu002Flargeu002Fpgc-imageu002F170d6236ed014125b0b2805aeb9a5432″ img_width=”830″ img_height=”80″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003Eu003Cstrongu003E2.2.3.3 优化前后平均时延对比u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E验证方式:u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E该集群所有节点加上网络IO复用配置后与默认配置的平均时延对比如下:u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp3.pstatp.comu002Flargeu002Fpgc-imageu002Fce7f3932fc654b938e94e88979d5e738″ img_width=”830″ img_height=”329″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E从上图可以看出,网络IO复用后时延降低了1-2倍。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E2.3 wiredtiger存储引擎优化u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E 从上一节可以看出平均时延从200ms降低到了平均80ms左右,很显然平均时延还是很高,如何进一步提升性能降低时延?继续分析集群,我们发现磁盘IO一会儿为0,一会儿持续性100%,并且有跌0现象,现象如下:u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp3.pstatp.comu002Flargeu002Fpgc-imageu002F8ecd8101d28d460d996924745e29ef22″ img_width=”830″ img_height=”565″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E从图中可以看出,Iu002FO写入一次性到2G,后面几秒钟内Iu002FO会持续性阻塞,读写Iu002FO完全跌0,avgqu-sz、awit巨大,util次序性100%,在这个Iu002FO跌0的过程中,业务方反应的TPS同时跌0。u003Cu002Fpu003Eu003Cpu003E此外,在大量写入IO后很长一段时间util又持续为0%,现象如下:u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002F6202645a570d44528e29244a02d6e7be” img_width=”830″ img_height=”287″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E总体IO负载曲线如下:u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp9.pstatp.comu002Flargeu002Fpgc-imageu002F1288604427db47bb88f0f3b6d7c88a28″ img_width=”780″ img_height=”281″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E从图中可以看出IO很长一段时间持续为0%,然后又飙涨到100%持续很长时间,当IO util达到100%后,分析日志发现又大量满日志,同时mongostat监控流量发现如下现象:u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp3.pstatp.comu002Flargeu002Fpgc-imageu002F40b2b28c48be40c592ea8548c73b5303″ img_width=”831″ img_height=”237″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002F53b96fcc3d8c442dac557bfde57672b6″ img_width=”830″ img_height=”226″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E从上可以看出我们定时通过mongostat获取某个节点的状态的时候,经常超时,超时的时候刚好是io util=100%的时候,这时候IO跟不上客户端写入速度造成阻塞。u003Cu002Fpu003Eu003Cpu003E有了以上现象,我们可以确定问题是由于IO跟不上客户端写入速度引起,第2章我们已经做了mongodb服务层的优化,现在我们开始着手wiredtiger存储引擎层面的优化,主要通过以下几个方面:u003Cu002Fpu003Eu003Col start=”1″u003Eu003Cliu003Ecachesize调整u003Cu002Fliu003Eu003Cliu003E脏数据淘汰比例调整u003Cu002Fliu003Eu003Cliu003Echeckpoint优化u003Cu002Fliu003Eu003Cu002Folu003Eu003Cpu003Eu003Cstrongu003E2.3.1 cachesize调整优化(为何cacheSize越大性能越差)u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E前面的IO分析可以看出,超时时间点和Iu002FO阻塞跌0的时间点一致,因此如何解决Iu002FO跌0成为了解决改问题的关键所在。u003Cu002Fpu003Eu003Cpu003E找个集群平峰期(总tps50万u002Fs)查看当时该节点的TPS,发现TPS不是很高,单个分片也就3-4万左右,为何会有大量的刷盘,瞬间能够达到10Gu002FS,造成IO util持续性跌0(因为IO跟不上写入速度)。继续分析wiredtiger存储引擎刷盘实现原理,wiredtiger存储引擎是一种B+树存储引擎,mongodb文档首先转换为KV写入wiredtiger,在写入过程中,内存会越来越大,当内存中脏数据和内存总占用率达到一定比例,就开始刷盘。同时当达到checkpoint限制也会触发刷盘操作,查看任意一个mongod节点进程状态,发现消耗的内存过多,达到110G,如下图所示:u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002Fb905a98ee26d4d42a4cca0e6b06af153″ img_width=”831″ img_height=”304″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E于是查看mongod.conf配置文件,发现配置文件中配置的cacheSizeGB: 110G,可以看出,存储引擎中KV总量几乎已经达到110G,按照5%脏页开始刷盘的比例,峰值情况下cachesSize设置得越大,里面得脏数据就会越多,而磁盘IO能力跟不上脏数据得产生速度,这种情况很可能就是造成磁盘Iu002FO瓶颈写满,并引起Iu002FO跌0的原因。u003Cu002Fpu003Eu003Cpu003E此外,查看该机器的内存,可以看到内存总大小为190G,其中已经使用110G左右,几乎是mongod的存储引起占用,这样会造成内核态的page cache减少,大量写入的时候内核cache不足就会引起磁盘缺页中断,引起大量的写盘。u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002F79e5f8b9b49640268a91368882187042″ img_width=”831″ img_height=”172″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003Eu003Cstrongu003E解决办法:u003Cu002Fstrongu003E通过上面的分析问题可能是大量写入的场景,脏数据太多容易造成一次性大量Iu002FO写入,于是我们可以考虑把存储引起cacheSize调小到50G,来减少同一时刻Iu002FO写入的量,从而规避峰值情况下一次性大量写入的磁盘Iu002FO打满阻塞问题。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E2.3.2 存储引擎dirty脏数据淘汰优化u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E调整cachesize大小解决了5s请求超时问题,对应告警也消失了,但是问题还是存在,5S超时消失了,1s超时问题还是偶尔会出现。u003Cu002Fpu003Eu003Cpu003E 因此如何在调整cacheSize的情况下进一步规避Iu002FO大量写的问题成为了问题解决的关键,进一步分析存储引擎原理,如何解决内存和Iu002FO的平衡关系成为了问题解决的关键,mongodb默认存储因为wiredtiger的cache淘汰策略相关的几个配置如下:u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002F5e1fc731c0b14e9aba1ed284084acc3b” img_width=”546″ img_height=”479″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E调整cacheSize从120G到50G后,如果脏数据比例达到5%,则极端情况下如果淘汰速度跟不上客户端写入速度,这样还是容易引起Iu002FO瓶颈,最终造成阻塞。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E解决办法: u003Cu002Fstrongu003E如何进一步减少持续性Iu002FO写入,也就是如何平衡cache内存和磁盘Iu002FO的关系成为问题关键所在。从上表中可以看出,如果脏数据及总内占用存达到一定比例,后台线程开始选择page进行淘汰写盘,如果脏数据及内存占用比例进一步增加,那么用户线程就会开始做page淘汰,这是个非常危险的阻塞过程,造成用户请求验证阻塞。平衡cache和Iu002FO的方法: 调整淘汰策略,让后台线程尽早淘汰数据,避免大量刷盘,同时降低用户线程阀值,避免用户线程进行page淘汰引起阻塞。优化调整存储引起配置如下:u003Cu002Fpu003Eu003Cpu003E eviction_target: 75%u003Cu002Fpu003Eu003Cpu003E eviction_trigger:97%u003Cu002Fpu003Eu003Cpu003E eviction_dirty_target: %3u003Cu002Fpu003Eu003Cpu003E eviction_dirty_trigger:25%u003Cu002Fpu003Eu003Cpu003E evict.threads_min:8u003Cu002Fpu003Eu003Cpu003E evict.threads_min:12u003Cu002Fpu003Eu003Cpu003E u003Cu002Fpu003Eu003Cpu003E总体思想是让后台evict尽量早点淘汰脏页page到磁盘,同时调整evict淘汰线程数来加快脏数据淘汰,调整后mongostat及客户端超时现象进一步缓解。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E2.3.3 存储引擎checkpoint优化调整u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E存储引擎得checkpoint检测点,实际上就是做快照,把当前存储引擎的脏数据全部记录到磁盘。触发checkpoint的条件默认又两个,触发条件如下:u003Cu002Fpu003Eu003Col start=”1″u003Eu003Cliu003E固定周期做一次checkpoint快照,默认60su003Cu002Fliu003Eu003Cliu003E增量的redo log(也就是journal日志)达到2Gu003Cu002Fliu003Eu003Cu002Folu003Eu003Cpu003E当journal日志达到2G或者redo log没有达到2G并且距离上一次时间间隔达到60s,wiredtiger将会触发checkpoint,如果在两次checkpoint的时间间隔类evict淘汰线程淘汰的dirty page越少,那么积压的脏数据就会越多,也就是checkpoint的时候脏数据就会越多,造成checkpoint的时候大量的IO写盘操作。如果我们把checkpoint的周期缩短,那么两个checkpoint期间的脏数据相应的也就会减少,磁盘IO 100%持续的时间也就会缩短。u003Cu002Fpu003Eu003Cpu003Echeckpoint调整后的值如下:u003Cu002Fpu003Eu003Cpu003Echeckpoint=(wait=25,log_size=1GB)u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E2.3.4 存储引擎优化前后IO对比u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E通过上面三个方面的存储引擎优化后,磁盘IO开始平均到各个不同的时间点,iostat监控优化后的IO负载如下:u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002Fa0b25de8c19b419096fd399e8e0268b2″ img_width=”831″ img_height=”563″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E从上面的io负载图可以看出,之前的IO一会儿为0%,一会儿100%现象有所缓解,总结如下图所示:u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002F3a4c6eb719044aaea749f37710947699″ img_width=”1080″ img_height=”810″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003Eu003Cbru002Fu003Eu003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E2.3.5 存储引擎优化前后时延对比u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E优化前后时延对比如下(注: 该集群有几个业务同时使用,优化前后时延对比如下):u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp9.pstatp.comu002Flargeu002Fpgc-imageu002F78a95d006c7c4b5cad5ae4012c1755f6″ img_width=”829″ img_height=”467″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp3.pstatp.comu002Flargeu002Fpgc-imageu002Fff8e67cc2370460a91f9acc2b5b67c33″ img_width=”829″ img_height=”440″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002Fa28e0e733b374983b0820f7d500e17a4″ img_width=”830″ img_height=”460″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp3.pstatp.comu002Flargeu002Fpgc-imageu002F3af97665de014e37bf178eba195bc675″ img_width=”830″ img_height=”567″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp3.pstatp.comu002Flargeu002Fpgc-imageu002Fecbfe3d91dc34c80ad810edc2bb1da4a” img_width=”684″ img_height=”432″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E从上图可以看出,存储引擎优化后时间延迟进一步降低并趋于平稳,从平均80ms到平均20ms左右,但是还是不完美,有抖动。u003Cu002Fpu003Eu003Ch1 class=”pgc-h-arrow-right”u003E3 服务器系统磁盘IO问题解决u003Cu002Fh1u003Eu003Cpu003Eu003Cstrongu003E3.1 服务器IO硬件问题背景u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E如第3节所述,当wiredtiger大量淘汰数据后,发现只要每秒磁盘写入量超过500Mu002Fs,接下来的几秒钟内util就会持续100%,wu002Fs几乎跌0,于是开始怀疑磁盘硬件存在缺陷。u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp9.pstatp.comu002Flargeu002Fpgc-imageu002F81ca355cf72a404ea2239da3a20b41ec” img_width=”698″ img_height=”475″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002F7bab8760793341189145b76c2b61576e” img_width=”538″ img_height=”143″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E从上图可以看出磁盘为nvMe的ssd盘,查看相关数据可以看出该盘IO性能很好,支持每秒2G写入,iops能达到2.5Wu002FS,而我们线上的盘只能每秒写入最多500M。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E3.2 服务器IO硬件问题解决后性能对比u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E于是考虑把该分片集群的主节点全部迁移到另一款服务器,该服务器也是ssd盘,io性能达到2Gu002Fs写入(注意:只迁移了主节点,从节点还是在之前的IO-500Mu002Fs的服务器)。 迁移完成后,发现性能得到了进一步提升,时延迟降低到2-4msu002Fs,三个不同业务层面看到的时延监控如下图所示:u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002Fab9f3a5d881e443fafd86c7f037eb8e6″ img_width=”831″ img_height=”518″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002Fb90c09ad264541819c0d703fc0295fa8″ img_width=”830″ img_height=”528″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002F0549578f63f849b68efe049185a7b50a” img_width=”831″ img_height=”457″ alt=”百万级高并发mongodb集群性能数十倍提升优化实践” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E从上图时延可以看出,迁移主节点到IO能力更好的机器后,时延进一步降低到平均2-4ms。u003Cu002Fpu003Eu003Cpu003E虽然时延降低到了平均2-4ms,但是还是有很多几十ms的尖刺,鉴于篇幅将在下一期分享大家原因,最终保存所有时延控制在5ms以内,并消除几十ms的尖刺。u003Cu002Fpu003Eu003Cpu003E此外,nvme的ssd io瓶颈问题原因,经过和厂商确认分析,最终定位到是linux内核版本不匹配引起,如果大家nvme ssd盘有同样问题,记得升级linux版本到3.10.0-957.27.2.el7.x86_64版本,升级后nvme ssd的IO能力达到2Gu002Fs以上写入。u003Cu002Fpu003Eu003Ch1 class=”pgc-h-arrow-right”u003E4 总结及遗留问题u003Cu002Fh1u003Eu003Cpu003E通过mongodb服务层配置优化、存储引擎优化、硬件IO提升三方面的优化后,该大流量写入集群的平均时延从之前的平均数百ms降低到了平均2-4ms,整体性能提升数十倍,效果明显。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E但是,u003Cu002Fstrongu003E从4.2章节优化后的时延可以看出,集群偶尔还是会有抖动,鉴于篇幅,下期会分享如果消除4.2章节中的时延抖动,最终保持时间完全延迟控制在2-4ms,并且无任何超过10ms的抖动,敬请期待,下篇会更加精彩。u003Cu002Fpu003Eu003Cpu003E此外,在集群优化过程中采了一些坑,下期会继续分析大流量集群采坑记。u003Cu002Fpu003E”

原文始发于:百万级高并发mongodb集群性能数十倍提升优化实践

主题测试文章,只做测试使用。发布者:乾奕,转转请注明出处:http://www.cxybcw.com/26308.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code