最新发布《数智时代的AI人才粮仓模型解读白皮书(2024版)》,立即领取! 了解详情
写点什么

无需扩容成本,百亿集群数据过期性能优化看这就行

  • 2021-07-15
  • 本文字数:3838 字

    阅读完需:约 13 分钟

无需扩容成本,百亿集群数据过期性能优化看这就行

某百亿级 mongodb 业务只保存近期 7 天的数据,由于数据量大、流量高,数据过期删除点比较集中,同时不能错峰方式解决问题,因此如何利用最小物理成本来满足业务需求就成为了本集群性能优化的难点。


通过几轮和业务配合调优,包括存储引擎调优、数据删除方式调优、业务错峰读写等,最终完美解决了业务痛点,达到 ms 级业务读写访问。

一、业务背景

线上某业务数据量约 100 亿,白天为写流量高峰期,峰值写约 14W/s,如下图所示:




业务每天白天生产数据,同时凌晨批量拉取过去几天数据做大数据分析,整个集群只保存最近七天数据。


单条数据约 800 字节,如下所示:


1.   {  2.        "_id" : ObjectId("608592008bd3dad61675b491"),  3.        "deviceSn" : "xxxxxxxxxxxxx",  4.        "itemType" : 0,  5.        "module" : "xxxxxx",  6.        "userId" : "xxxxx",  7.        "callTimes" : NumberLong(2),  8.        "capacityAdd" : NumberLong(0),  9.        "capacityDelete" : ”xxxxxxxx”,  10.        "capacityDownload" :”xxxxxxxxxxxx”,  11.        "capacityModify" : ”xxxxxxxxxxxx”,  12.        "createTime" : NumberLong("1619366400003"),  13.        "expireAt" : ISODate("2021-05-02T22:53:45.497Z"),  14.        "numAdd" : NumberLong(2),  15.        "numDelete" : NumberLong(345),  16.        "numDownload" : NumberLong(43),  17.        "numModify" : NumberLong(3),  18.        "osVersion" : "xxxx",  19.        "reversedUserId" : "xxxxx",  20.        "updateTime" : NumberLong("1619366402106")  
复制代码

二、mongodb 资源评估及部署架构

通过和业务对接梳理,该集群规模及业务需求总结如下:

  • 数据量百亿级

  • 单条数据 800 字节,100 亿条预计 7.5T 数据

  • 读写分离

所有数据只保留七天

2.1 mongodb 资源评估

分片数及存储节点套餐规格选定评估过程如下:


  • 内存评估

我司都是容器化部署,以以往经验来看,mongodb 对内存消耗不高,历史百亿级以上 mongodb 集群单个容器最大内存基本上都是 64Gb,因此内存规格确定为 64G。


  • 分片评估

 业务流量峰值 10W/s 多,预计需要 3 个分片支持读写。


  • 磁盘评估

100 亿数据 7.5T,由于 mongodb 默认有高压缩,预计真实磁盘占用 2.5~3T 左右。三个分片,一个分片刚好 1T。


  • CPU 规格评估

由于容器调度套餐化限制,因此 CPU 只能限定为 16CPU(实际上用不了这么多 CPU)。


  • mongos 代理及 config server 规格评估

此外,由于分片集群还有 mongos 代理和 config server 复制集,因此还需要评估 mongos 代理和 config server 节点规格。由于 config server 只主要存储路由相关元数据,因此对磁盘、CUP、MEM 消耗都很低;mongos 代理只做路由转发只消耗 CPU,因此对内存和磁盘消耗都不高。最终,为了最大化节省成本,我们决定让一个代理和一个 config server 复用同一个容器,容器规格如下:


8CPU/8G 内存/50G 磁盘,一个代理和一个 config server 节点复用同一个容器。


分片及存储节点规格总结:4 分片/16CPU、64G 内存、1T 磁盘。


mongos 及 config server 规格总结:8CPU/8G 内存/50G 磁盘


节点类型

单个节点容器规格

说明

shardServer存储节点

16CPU64G内存、1T磁盘

1个分片存储约30亿数据

3个分片预计存储100亿数据

mongosconfig server节点

8CPU/8G内存/50G磁盘

一个代理和一个config server节点复用同一个容器

2.2 集群部署架构

该业务数据不是很重要,为了节省成本,因此我们采用 2+1 模式部署,也就是:2mongod+1arbiter 模式,同城机房部署,部署架构图如下图所示:



考虑到数据重要性不高,通过 2mongod+1arbiter 模式即可满足用户要求,同时可以最大化节省成本。

三、性能优化过程

该集群优化过程按照如下两个步骤优化:业务使用集群前的性能优化、业务使用过程中的性能优化。


业务提前建好查询对应的最优索引,同时创建过期索引:



db.dailyCloudOperateInfo.createIndex( { "createTime": 1 }, { expireAfterSeconds: 604800} )
复制代码

3.1  业务使用集群前的性能优化

和业务沟通确定,业务每条数据都携带有一个设备标识 userId,同时业务查询更新等都是根据 userId 维度查询该设备下面的单条或者一批数据,因此片建选择 userId。


  • 分片方式

为了充分散列数据到 3 个分片,因此选择 hash 分片方式,这样数据可以最大化散列,同时可以满足同一个 userId 数据落到同一个分片,保证查询效率。


  • 预分片

mongodb 如果分片片建为 hashed 分片,则可以提前做预分片,这样就可以保证数据写进来的时候比较均衡的写入多个分片。预分片的好处可以规避非预分片情况下的 chunk 迁移问题,最大化提升写入性能。



sh.shardCollection("cloud_track.dailyCloudOperateInfo", {userId:"hashed"}, false, { numInitialChunks: 8192} )
复制代码


  • 就近读

客户端增加 secondaryPreferred 配置,优先读从节点。


  • 禁用 enable Majority Read Concern

禁用该功能后 Read Concern majority 将会报错,Read Concern majority 功能注意是避免脏读,和业务沟通业务没该需求,因此可以直接关闭。


mongodb 默认使能了 enable Majority Read Concern,该功能开启对性能有一定影响,参考:


MongoDB readConcern 原理解析:

https://developer.aliyun.com/article/60553


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

https://mongoing.com/archives/29934


  • 存储引擎 cacheSize 规格选择

单个容器规格:16CPU、64G 内存、7T 磁盘,考虑到全量迁移过程中对内存压力,内存碎片等压力会比较大,为了避免 OOM,设置 cacheSize=42G。

3.2  业务使用过程中遇到的问题及性能优化

1)第一轮优化:存储引擎优化

业务高峰期主要是数据写入和更新,内存脏数据较多,当脏数据比例达到一定比例后用户读写请求对应线程将会阻塞,用户线程也会去淘汰内存中的脏数据 page,最终写性能下降明显。


wiredtiger 存储引擎 cache 淘汰策略相关的几个配置如下:



由于业务全量迁移数据是持续性的大流量写,而不是突发性的大流量写,因此 eviction_target、eviction_trigger、eviction_dirty_target、eviction_dirty_trigger 几个配置用处不大,这几个参数阀值只是在短时间突发流量情况下调整才有用。


但是,在持续性长时间大流量写的情况下,我们可以通过提高 wiredtiger 存储引擎后台线程数来解决脏数据比例过高引起的用户请求阻塞问题,淘汰脏数据的任务最终交由 evict 模块后台线程来完成。


全量大流量持续性写存储引擎优化如下:



db.adminCommand( { setParameter : 1, "wiredTigerEngineRuntimeConfig" : "eviction=(threads_min=4, threads_max=20)"})
复制代码

2)第一轮优化后存在的问题

经过存储引擎后台线程数的调优后,数据写入和更新瓶颈解决,写入和更新过程时延都很平滑。但是随着一周后开始数据过期,业务写开始大量抖动,如下所示:



从上图可以看出平均时延极端情况下甚至达到了几百 ms,这是业务完全接受不了的。通过 mongostat 监控发现如下现象:


  • 主节点 mongostat 监控统计



从上面的监控可以看出,三个分片的每个主节点只有 4000 左右的写更新操作(注意:实际上还有 4 万左右的 delete 操作,由于主节点过期 delete 不会统计,因此只能通过从节点查看,详见后面分析,实际单个分片主节点写和删除操作 4.4W/s),写流量很低。但是,监控中的脏数据比例持续性的超过 20%,超过 20%后业务的请求就需要进行脏数据淘汰,最终造成业务请求阻塞抖动。


通过前面的分析可以看出,业务正常峰值写入 3 个分片差不多 10W/s。一星期后,七天前的数据需要过期,这时候过期删除的 ops 也需要 delete 删除 10w/S,由于这时候新数据同样按照 10w/s 写入,因此集群就需要支持 20w/s 的 ops 操作才能支持。


显然,3 个分片支持不了持续性的 20w/s 左右的 ops 操作,因此如何不扩容情况下支撑业务需求将是一大难点。


  • 为何 ttl 过期主节点没用 delete 统计



上图为 mongodb 单机模块架构图,主节点默认启用一个 TTLMonitor 线程,借助查询引起模块实时扫描过期索引,然后把满足条件的数据删除。整个删除过程没有走 command 命令处理模块,而命令计数操作只会在 command 模块计数,因此主节点的过期删除不会有 delete 操作。


命令处理模块处理流程及其计数统计详见:

mongodb 内核源码模块化设计与实现专栏


更多 mongodb 模块化源码设计实现详见:

https://github.com/y123456yz/reading-and-annotate-mongodb-3.6

3.3  第二轮优化(过期删除放凌晨低峰期)-不可行

从前面的分析可以看出,我们三个分片支撑不了持续性 20W/S 的更新和删除操作,因此我们考虑业务改造使用方式,把过期删除确定到凌晨低峰期。


但是业务上线后出现其他的问题,由于业务凌晨会持续性的批量拉取分析过去几天的数据,如果过期和批量读数据叠加到一起,严重影响业务查询效率。最终,该方案不可行,如果不扩容,则需要其他方案。

3.4  第三轮方案优化(天维度建表,过期删表)

为了不增加成本,同时 3 个分片又支撑不了 20W/s 的读写删除等导致,为了尽量通过 3 个分片不扩容条件下来满足用户需求,因此转变方式,通过删表的方式来避免过期,具体实现如下:


  • 业务改造代码,以天为单位建表,每天的数据存到对应的表中。

  • 建表后业务启用预分片功能,确保数据均衡分布到三个分片。

  • 业务保存 8 天数据,第九天凌晨删除第一天的表


    该方案业务时延统计对应收益如下:




如上图所示,通过过期方式的优化,最终问题彻底解决,并且读写时延控制在 0.5ms-2ms。

四、优化收益总结

通过前面的一系列优化,最终没有扩容,并且解决了业务过期和大量数据写入更新引起的时延抖动问题,总体收益如下:


  • 改造优化前时延:经常几百 ms 抖动

  • 改造优化后时延:0.5-2ms


作者介绍

杨亚洲,前滴滴出行专家工程师,现任 OPPO 文档数据库 mongodb 负责人,负责数万亿级数据量文档数据库 mongodb 内核研发、性能优化及运维工作,一直专注于分布式缓存、高性能服务端、数据库、中间件等相关研发。


本文转载自:dbaplus 社群(ID:dbaplus)

原文链接:无需扩容成本,百亿集群数据过期性能优化看这就行!


2021-07-15 13:001183

评论

发布
暂无评论
发现更多内容

细说JavaScript正则表达式(RegExp)

devpoint

正则表达式 regex JavaScrip 8月日更

缓存知识总结

十二万伏特皮卡丘

马士兵老师亲自总结3000+道Java面试题,刷完吊打架构师面试官

Java 程序员 架构 面试 计算机

秒杀系统设计-超卖问题

泽睿

秒杀 秒杀系统

我为什么不建议大家等公司倒闭之后,再找工作!

非著名程序员

面试 认知提升 招聘管理 8月日更

一夜标星过百万,轻松霸榜GitHub的手绘图解HTTP笔记,竟来源阿里

Java~~~

Java 架构 面试 网络 HTTP

MySQL 系列教程之(三) MySQL 基本概念和操作

若尘

MySQL 8月日更

“硬钢字节”阿里大牛分享内部数据结构与算法(诛仙版)源码笔记

Java~~~

Java 架构 面试 算法 数据结构与算法

DAPP钱包开发模式详细介绍

Geek_23f0c3

dapp 钱包系统开发 DAPP智能合约交易系统开发

校友名片小程序设计方案

CC同学

小程序云开发 校友小程序

网络攻防学习笔记 Day105

穿过生命散发芬芳

态势感知 网络攻防 8月日更

Alibaba22届校招启动!连夜整理一份七大专题Java架构速成笔记

Java~~~

Java 架构 面试 阿里 校招

被boss直聘转发过多而“封杀”的2021年全套java高级面试题有多牛

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

MySQL 系列教程之(二)Windows 安装 MySQL5.7.17

若尘

MySQL 8月日更

猎杀时刻!阿里高工总结698页Spring学习笔记,疯狂狩猎大厂offer

Java~~~

Java spring 架构 面试 微服务

一切努力似乎都徒劳?|靠谱点评

无量靠谱

FastApi-14-文件上传-2

Python研究所

FastApi 8月日更

解除限制!Alibaba不在低调,P8大神纯手撸300页Java高并发手册

Java~~~

Java 架构 面试 高并发 架构师

Alibaba12年技术老兵整理的“MySQL 学习笔记”带你轻松拿捏MySQL

Java~~~

Java MySQL 数据库 架构 面试

腾讯跟阿里两位王者之间的对比

Linux服务器开发

腾讯 阿里 C/C++ Linux服务器开发 Linux后台开发

这份阿里P8级别内部疯传的“Linux私房菜”让你一次吃个饱

Java 编程 程序员 IT 计算机

上线仅仅三小时,豆瓣评分均9.0的“四本程序员必刷书籍”火了

Java 编程 面试 IT 计算机

大专的我狂刷29天“阿里内部面试笔记”最终直接斩获十七个Offer

Java 程序员 架构 面试 IT

【LeetCode】股票的最大利润Java题解

Albert

算法 LeetCode 8月日更

爆款阿里P5到P7晋升之路,九大源码文档助我超神果然努力幸运并存

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

终于拿到了阿里2021年度九大Java技术文档——面试题+文档+白皮书

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

网络安全证书合集系列

网络安全学海

网络安全 证书 信息安全 渗透测试 安全漏洞

Java的四种引用类型

W🌥

Java JVM 8月日更

前方高能!Alibaba最新出版的JDK源码剖析手册(究极奥义版)开源

Java~~~

Java 架构 jdk 面试 架构师

netty系列之:使用UDP协议

程序那些事

Java Netty nio udp 程序那些事

震惊!300多页美团百亿级系统架构设计实录首公开

Java 编程 架构 面试 架构师

无需扩容成本,百亿集群数据过期性能优化看这就行_大数据_dbaplus社群_InfoQ精选文章