您当前的位置:首页 > 电脑百科 > 数据库 > 百科

数亿数据MySQL撑不住,无缝迁移到MongoDB后稳得一批

时间:2022-07-05 11:30:24  来源:  作者:dbaplus社群

一、问题

 

在好大夫在线内部,S3系统负责各业务方操作日志的集中存储、查询和管理。目前,该系统日均查询量数千万次,插入量数十万次。随着日志量的不断累积,主表已经达到数十亿,单表占用磁盘空间400G+。S3是业务早期就存在的系统,当时为了简单快速落地,使用了MySQL来存储,随着业务的不断增长,同时也要兼顾性能和可扩展性,到了必须要重新选型的时候了。

 

新项目命名为:LogStore。

 

二、目标

 

1、安全性

 

S3系统在设计之初,没有按业务系统考虑数据隔离,而是直接采用 key(系统 + 类名 + id) + 有限固定字段 + 序列化value 的方式进行存储,这种方式显然不便于后续集群拆分和管理。LogStore系统要在逻辑上进行数据区域划分,业务方在接入时要指定App进行必要的权限验证,以区分不同业务数据,进而再进行插入和查询操作。

 

2、通用性

 

S3主要提供一种3层结构,采用MySQL固定字段进行存储,这就不可避免地会造成字段空间的浪费。LogStore系统需要提供一种通用的日志存储格式,由业务方自行规定字段含义,并且保留一定程度的可查询维度。

 

3、高性能

 

S3系统的QPS在300+,单条数据最大1KB左右。LogStore系统要支持当前QPS 10倍以上的写入和读取速度。

 

4、可审计

 

要满足内部安全审计的要求,LogStore系统不提供对数据的更新,只允许数据的插入和查询。

 

5、易拓展

 

LogStore系统以及底层存储要满足可扩展特性,可以在线扩容,满足公司未来5年甚至更长时间的日志存储需求,并且要最大化节省磁盘空间。

 

三、方案选型

 

为了达成改造目标,本次调研了四种存储改造方案,各种方案对比如下:

数亿数据MySQL撑不住,无缝迁移到MongoDB后稳得一批

 

1、我们不合适—分库分表

 

分库分表主要分为应用层依赖类中间件和代理中间件,无论哪种均需要修改现有phpJAVA框架,同时对DBA管理数据也带来一定的操作困难。为了降低架构复杂度,架构团队否定了引入DB中间件的方案,还是要求运维简单、成本低的方案。

 

2、我们不合适—TiDB

 

TiDB也曾一度进入了我们重点调研对象,只是由于目前公司的DB生态主要还是在MGR、MongoDB、MySQL上,在可预见的需求中,也没有能充分发挥TiDB的场景,所以就暂时搁置了。

 

3、我们不合适—ElasticSearch

 

ELK-stack提供的套件确实让ES很有吸引力,公司用ES集群也有较长时间了。ES优势在于检索和数据分析领域,也正是因为其检索和分析的功能的强大,无论写入、查询和存储成本都比较高,在日志处理的这个场景下,性价比略低,所以也被pass了。

 

4、适合的选择—MongoDB

 

业务操作日志读多写少,很适合文档型数据库MongoDB的特点。同时,MongoDB在业界得到了广泛的使用,公司也有很多业务在使用,在MongoDB上积累了一定的运维经验,最终决定选择MongoDB作为新日志系统存储方案。

 

四、性能测试

 

为了验证MongoDB的性能能否达到要求,我们搭建了MongoDB集群,机器配置、架构图和测试结果如下:

 

1、机器配置

 

MongoDB集群3台机器配置如下:

数亿数据MySQL撑不住,无缝迁移到MongoDB后稳得一批

 

2、架构图

数亿数据MySQL撑不住,无缝迁移到MongoDB后稳得一批

 

3、测试场景

 

本次MongoDB测试采用YCSB(
https://Github.com/brianfrankcooper/YCSB)性能测试工具,ycsb的workloads目录下保存了6种不同的workload类型,代表了不同的压测负载类型,本次我们只用到了其中5种,具体场景和测试结果如下。

数亿数据MySQL撑不住,无缝迁移到MongoDB后稳得一批

 

1) 插入平均文档大小为5K,数据量为100万,并发100,数据量总共5.265G 左右,执行的时间以及磁盘压力

 

结论:插入100w数据,总耗时219s,平均 insert 耗时21.8ms,吞吐量 4568/s

 

2) 测试90%读,10%更新,并发100的场景

 

结论:总耗时236s,read 平均耗时23.6ms, update 平均耗时23.56ms,吞吐量达到 4225/s

 

3) 测试读多写少,100%读 ,并发100的场景

 

结论:总耗时123s,平均read 耗时12.3ms,吞吐量达到8090/s

 

4) 测试读多写少,90%读,10%插入,并发100的场景

 

结论:总耗时220s,read 平均耗时 21.9ms,insert 平均耗时21.9ms,吞吐量达到4541/s

 

5) 测试混合读写,50%读,25%插入、25%更新,并发100的场景

 

结论:总耗时267s,read 平均耗时26.7ms,update 平均耗时26.7ms,insert 平均耗时26.6ms ,吞吐量 为3739/s

 

4、测试结果对比

数亿数据MySQL撑不住,无缝迁移到MongoDB后稳得一批

 

可以看出mongodb适合读多写少的时候,性能最好,读写速率能满足生产需求。

 

五、无缝迁移实践

 

为了保障业务的无缝迁移,也为了最大化降低业务研发同学的投入成本,我们决定采用分阶段切换的方案。

 

1、系统应用层改造+LogStore系统搭建

 

首先,在S3系统中内置读开关和写开关,可将读写流量分别引入到LogStore系统中,而新应用的接入可以直接调用LogStore系统,此时结构示意图如下:

数亿数据MySQL撑不住,无缝迁移到MongoDB后稳得一批

 

2、增量数据同步

 

为了让S3系统和LogStore系统中新增数据达到一致,在底层数据库采用Maxwell订阅MySQL Binlog的方式同步到MongoDB中,示意图如下:

 

Maxwell(http://maxwells-daemon.io)实时读取MySQL二进制日志binlog,并生成 JSON 格式的消息,作为生产者发送给 Kafka,Logstore系统消费Kafka中的数据写入到mongodb数据库中。

 

至此,对于业务方现有日志类型,新增数据在底层达到双写目的,S3系统和LogStore系统存储两份数据;如果业务方新增日志类型,则直接调用LogStore系统接口即可。接下来,我们将对已有日志类型老数据进行迁移。

数亿数据MySQL撑不住,无缝迁移到MongoDB后稳得一批

 

3、存量数据迁移

 

此次迁移S3老数据采用php定时任务脚本(多个)查询数据,将数据投递到RabbitMQ队列中,LogStore系统从RabbitMQ队列拉取消息进行消费存储到MongoDB中,示意图如下:

数亿数据MySQL撑不住,无缝迁移到MongoDB后稳得一批

 

  • 由于原mysql表中id为varchar类型并且非主键索引,只能利用ctime索引分批次进行查询,数据密集处进行chunk投递到mq队列中。

 

  • 数据无法一天就迁移完,迁移过程中可能存在中断的情况。脚本采用定时任务每天执行20h, 在上线时间停止执行,同时将停止时间记录到redis中。

 

  • 由于需要迁移数据量较大,在mq和消费者能承受的情况下,尽可能多地增加脚本数量,缩短导数据的时间。

 

  • 脚本执行期间,观察业务延时情况和MySQL监控情况,发现有影响立即进行调整,以保障不影响正常业务。

 

4、检验数据

 

老数据导入完成后,下面就要对老数据进行校验,校验从两个方面进行: 数据量和数据完整性。

 

1)数据量

 

基于S3系统老数据的id, 查询在MongoDB中是否存在,如果不存在则进行补偿重发。

 

2)数据完整性

 

对于S3和MongoDB中的数据按照相同规则进行md5校验,校验不通过则进行补偿重发。

数亿数据MySQL撑不住,无缝迁移到MongoDB后稳得一批

 

5、数据双写

 

将应用层预制的写开关打开,将流量导入到LogStore中,此时mysql的流量并没有停掉,继续执行binlog同步。结构如下:

数亿数据MySQL撑不住,无缝迁移到MongoDB后稳得一批

 

从图中可以看到,从S3调用点的写接口的流量都写入到MongoDB数据库backuplogs集合中,为什么不直接写入到logs表中呢?留个小悬念,在后文中有解释。

 

6、灰度切换S3读到LogStore系统

 

上文我们提到,对于S3系统应用层读写调用点均分别内置了切换开关,打开应用层读开关,所有的读操作全部走LogStore, 切换后示意图如下所示:

数亿数据MySQL撑不住,无缝迁移到MongoDB后稳得一批

 

7、灰度切换写接口到LogStore系统

 

打开应用层写开关,所有写操作会通过mq异步写到MongoDB中,那如何证明应用层写调用点修改完全了呢?

 

上文中双写数据一份到logs表中,一份到backuplogs表中,通过Maxwell的Binlog同步的数据肯定是最全的,数据量上按理来说 count( logs) >= count(backuplogs), 如果两个集合一段时间内的数据增量相同,则证明写调用点修改完全,可以去掉双写,只保留LogStore这条线,反之需要检查修改再次验证。切换写完成后,示意图如下:

数亿数据MySQL撑不住,无缝迁移到MongoDB后稳得一批

 

六、MongoDB与故障演练

 

故障演练能够检测服务是否真正高可用,及时发现系统薄弱的环节,提前准备好预案减少故障恢复时间。为了验证MongoDB是否真正高可用,我们在线下搭建了MongoDB集群:

数亿数据MySQL撑不住,无缝迁移到MongoDB后稳得一批

 

同时,我们编写脚本模拟用户MongoDB数据插入和读取,基于好大夫在线自研故障演练平台,对机器进行故障注入,查看各种故障对用户的影响。故障演练内容CPU、内存、磁盘、网络和进程Kill等操作,详情如下图所示:

数亿数据MySQL撑不住,无缝迁移到MongoDB后稳得一批

 

实验结果:

 

  • CPU、磁盘填充和磁盘负载对MongoDB集群影响较小。

 

  • 内存满载可能会发生系统OOM,导致MongoDB进程被操作系统Kill,由于MongoDB存在数据副本和自动主从切换,对用户影响较小。

 

  • 网络抖动、延迟和丢包会导致mongos连接服务器时间变长,客户端卡顿的现象发生,可通过网络监控的手段监测。

 

  • 分别主动Kill掉MongoDB的主节点、从节点、仲裁节点、mongos、config节点,对整个集群影响较小。

 

整体而言,MongoDB存在副本和自动主从切换,客户端存在自动检测重连机制,单个机器发生故障时对整体集群可用性影响较小。同时,可增加对单机器的资源进行监控,达到阈值进行报警,减小故障发现和恢复时间。

 

七、总结

 

1、MongoDB的使用

 

MongoDB数据写入可能各个分片不均匀,此时可以开启块均衡策略;由于均衡器会增加系统负载,最好选择在业务量较小的时候进行;

 

合理选择分片键和建立索引,会使你的查询速度更快,这个要具体场景具体分析。

 

2、迁移数据

 

必须保留唯一标识数据的字段,最好是主键id,方便校验数据;

 

一定要考虑多进程,脚本要自动化,缩短迁移时间和减小人工介入;

 

迁移过程中,要时刻关注数据库、中间件及应用相关指标,防止导出导入数据影响正常业务;

 

要在同样配置的环境下充分演练,提前制定数据比对测试用例,以防止数据丢失;

 

每一步线上操作(如切换读写),都要有对应的回滚计划,最大限度降低对业务的影响。

 

作者丨孙文华

来源丨公众号:HaoDF技术团队(ID:haodf_tech)

dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn

 

关于我们

dbaplus社群是围绕Database、BigData、AIOps的企业级专业社群。资深大咖、技术干货,每天精品原创文章推送,每周线上技术分享,每月线下技术沙龙,每季度Gdevops&DAMS行业大会。

关注公众号【dbaplus社群】,获取更多原创技术文章和精选工具下载



Tags:MongoDB   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
MongoDB 大量数据插入时的性能影响及解决方法
MongoDB 是一种广泛应用的 NoSQL 数据库,以其高度可扩展性和灵活性而闻名。然而,在处理大量数据时,MongoDB 的性能可能会受到一些影响。大量数据插入对 MongoDB 性能的影响磁盘...【详细内容】
2024-01-05  Search: MongoDB  点击:(134)  评论:(0)  加入收藏
Java操作MongoDB如何批量写入数据
当需要插入、更新或删除大量文档时,一次执行多个操作比分别执行每个操作要快得多。批量操作减少了网络往返次数,减少了I/O负载,并且可能允许数据库引擎更有效地利用内部缓存和...【详细内容】
2023-12-19  Search: MongoDB  点击:(99)  评论:(0)  加入收藏
解析MongoDB的并发控制和事务隔离级别:保证数据一致性
MongoDB 是一个高性能的文档型数据库,支持多维度的并发控制和事务隔离级别,以保证数据一致性。接下来,下面将详细讲解 MongoDB 的并发控制和事务隔离级别。一、并发控制MongoDB...【详细内容】
2023-12-19  Search: MongoDB  点击:(108)  评论:(0)  加入收藏
MongoDB与大数据处理:构建高性能分布式数据库
MongoDB是一种非关系型数据库,具有高度灵活性和可扩展性。在处理大量数据时,索引的优化是提升查询性能的关键。下面将介绍一些MongoDB索引优化的指南,帮助用户更好地利用索引来...【详细内容】
2023-12-18  Search: MongoDB  点击:(73)  评论:(0)  加入收藏
MongoDB索引优化指南:提升查询性能的关键
MongoDB是一种非关系型数据库,具有高度灵活性和可扩展性。在处理大量数据时,索引的优化是提升查询性能的关键。下面将介绍一些MongoDB索引优化的指南,帮助用户更好地利用索引来...【详细内容】
2023-12-14  Search: MongoDB  点击:(124)  评论:(0)  加入收藏
Mongodb和Elasticsearch计算经纬度哪个性能更好
MongoDB和Elasticsearch都支持计算经纬度距离,但它们的性能表现可能因使用场景和数据规模而异。性能对比1、数据索引和存储 MongoDB使用地理空间索引(2dsphere)来支持经纬度数...【详细内容】
2023-12-11  Search: MongoDB  点击:(231)  评论:(0)  加入收藏
解密MongoDB集群管理:构建高可用性数据库架构
MongoDB集群管理是指在MongoDB数据库环境中构建高可用性的数据库架构,以确保数据的持久性、可用性和性能。下面将详细介绍构建高可用性数据库架构的相关概念、方法和步骤。一...【详细内容】
2023-12-06  Search: MongoDB  点击:(147)  评论:(0)  加入收藏
Java和MongoDB的异常检测
构建实时监控和告警系统是当今许多企业和组织所需要的关键功能之一。Java和MongoDB的异常检测是这样的一个监控系统中的重要组成部分。下面将详细介绍如何使用Java和MongoDB...【详细内容】
2023-11-23  Search: MongoDB  点击:(213)  评论:(0)  加入收藏
构建高可用的MongoDB部署架构:应对故障和灾难恢复
MongoDB 是一种流行的 NoSQL 数据库,广泛用于各种规模的应用程序。为了确保数据的高可用性和灾难恢复能力,构建一个可靠的 MongoDB 部署架构至关重要。本文将重点介绍如何构建...【详细内容】
2023-11-21  Search: MongoDB  点击:(210)  评论:(0)  加入收藏
Java与MongoDB的定时任务管理
构建一个高效的任务调度系统对于许多应用程序来说是至关重要的。下面将探讨如何使用Java和MongoDB来实现一个可靠且高效的定时任务管理系统。一、概述任务调度系统是一种将...【详细内容】
2023-11-16  Search: MongoDB  点击:(218)  评论:(0)  加入收藏
▌简易百科推荐
向量数据库落地实践
本文基于京东内部向量数据库vearch进行实践。Vearch 是对大规模深度学习向量进行高性能相似搜索的弹性分布式系统。详见: https://github.com/vearch/zh_docs/blob/v3.3.X/do...【详细内容】
2024-04-03  京东云开发者    Tags:向量数据库   点击:(9)  评论:(0)  加入收藏
原来 SQL 函数是可以内联的!
介绍在某些情况下,SQL 函数(即指定LANGUAGE SQL)会将其函数体内联到调用它的查询中,而不是直接调用。这可以带来显著的性能提升,因为函数体可以暴露给调用查询的规划器,从而规划器...【详细内容】
2024-04-03  红石PG  微信公众号  Tags:SQL 函数   点击:(7)  评论:(0)  加入收藏
如何正确选择NoSQL数据库
译者 | 陈峻审校 | 重楼Allied Market Research最近发布的一份报告指出,业界对于NoSQL数据库的需求正在持续上升。2022年,全球NoSQL市场的销售额已达73亿美元,预计到2032年将达...【详细内容】
2024-03-28    51CTO  Tags:NoSQL   点击:(19)  评论:(0)  加入收藏
为什么数据库连接池不采用 IO 多路复用?
这是一个非常好的问题。IO多路复用被视为是非常好的性能助力器。但是一般我们在使用DB时,还是经常性采用c3p0,tomcat connection pool等技术来与DB连接,哪怕整个程序已经变成以...【详细内容】
2024-03-27  dbaplus社群    Tags:数据库连接池   点击:(19)  评论:(0)  加入收藏
八个常见的数据可视化错误以及如何避免它们
在当今以数据驱动为主导的世界里,清晰且具有洞察力的数据可视化至关重要。然而,在创建数据可视化时很容易犯错误,这可能导致对数据的错误解读。本文将探讨一些常见的糟糕数据可...【详细内容】
2024-03-26  DeepHub IMBA  微信公众号  Tags:数据可视化   点击:(11)  评论:(0)  加入收藏
到底有没有必要分库分表,如何考量的
关于是否需要进行分库分表,可以根据以下考量因素来决定: 数据量和负载:如果数据量巨大且负载压力较大,单一库单一表可能无法满足性能需求,考虑分库分表。 数据增长:预估数据增长...【详细内容】
2024-03-20  码上遇见你  微信公众号  Tags:分库分表   点击:(17)  评论:(0)  加入收藏
在 SQL 中写了 in 和 not in,技术总监说要炒了我……
WHY?IN 和 NOT IN 是比较常用的关键字,为什么要尽量避免呢?1、效率低项目中遇到这么个情况:t1表 和 t2表 都是150w条数据,600M的样子,都不算大。但是这样一句查询 ↓select *...【详细内容】
2024-03-18  dbaplus社群    Tags:SQL   点击:(13)  评论:(0)  加入收藏
应对慢SQL的致胜法宝:7大实例剖析+优化原则
大促备战,最大的隐患项之一就是慢SQL,对于服务平稳运行带来的破坏性最大,也是日常工作中经常带来整个应用抖动的最大隐患,在日常开发中如何避免出现慢SQL,出现了慢SQL应该按照什...【详细内容】
2024-03-14  京东云开发者    Tags:慢SQL   点击:(13)  评论:(0)  加入收藏
过去一年,我看到了数据库领域的十大发展趋势
作者 | 朱洁策划 | 李冬梅过去一年,行业信心跌至冰点2022 年中,红衫的一篇《适应与忍耐》的报告,对公司经营提出了预警,让各个公司保持现金流,重整团队,想办法增加盈利。这篇报告...【详细内容】
2024-03-12    InfoQ  Tags:数据库   点击:(37)  评论:(0)  加入收藏
SQL优化的七个方法,你会哪个?
一、插入数据优化 普通插入:在平时我们执行insert语句的时候,可能都是一条一条数据插入进去的,就像下面这样。INSERT INTO `department` VALUES(1, '研发部(RD)', &#39...【详细内容】
2024-03-07  程序员恰恰  微信公众号  Tags:SQL优化   点击:(24)  评论:(0)  加入收藏
站内最新
站内热门
站内头条