MySQL如何发型不乱的应对半年数十TB数据增量

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介:

文章出自:听云博客

       前段时间,Oracle官方发布了MySQL 5.7的GA版本。新版本中实现了真正意义的并行复制(基于Group Commit的Group Replication),而不再是基于schema的并行复制。这一特性极大的改善了特定场景下的主从复制延迟过高的状况。随着MySQL成熟度的提升,越来越多的用户选择使用MySQL存放自家的数据,其中不乏使用MySQL来存放大量数据的。

       在过去的半年多时间里,听云业务量呈爆发式增长,后端的数据量由去年第一季度的几TB增长到几十TB,业务量翻了十几倍。后端应用及数据库面临的一个突出的问题就是频繁的进行扩容来应对前端流量的增长。数据库层面我们使用MySQL来分布式存储业务数据,数据库集群的架构也比较简单,我们使用开源中间件Amoeba来实现数据的拆分和读写分离。Amoeba后端有几百个数据库的节点组,每个节点组中都包含一对主从实例。master实例负责接受write请求,slave负责接受query请求。如下图:

2.23.png 

正确的拆分姿势

       随着可选择的开源中间件越来越多,好多数据量并不是很大的使用者都会过早的考虑水平拆分数据库。但其实过早的水平拆分未见得是一件有意义的事情。主要原因有两个:一个方面是水平拆分会对现网的业务造成冲击,如果系统在设计之初就没有考虑过后续要进行拆分的话,这个冲击就会被放大。比如业务中有大量的多表join的查询,或者是对事务有强一致性的要求时,水平拆分就捉襟见肘了。另一方面,如果过早的进行了水平拆分,那么到达一定程度后再想要垂直进行拆分时,代价是很大的。以听云app为例,当我们业务库拆成8个分片后,有一天发现数据增长的很快,于是决定对其进行垂直拆分,将小时纬度和天纬度的数据拆分到一个新的实例上去,这时我们不得不同时部署8个节点组来将现有的8个分片上的小时纬度和天纬度的数据迁移出来。工作量相当大。如果水平拆分到了64个片,那么这时要想再做垂直拆分,保证累的你不要不要的。

       所以更合理的路线是这样的,首先对业务数据进行垂直拆分,原本一个库按业务单元垂直拆分成多个库,同时应用中配置多个数据源或者使用中间件来访问拆分后的多个库,对应用本身来说,基本没做什么改动,但是后端存储的容量和性能却翻了好几倍。如果某天出现瓶颈之后,再来考虑水平拆分的事情。

优雅的从n到2n

2.45.png 

       水平扩展过程中最让人头疼的是数据的迁移,以上图中迁移mod(mobile_app_id,4)=2的数据为例,最开始的做法是先创建两个新的节点组shared0_new和shared2,拿shared0的全备恢复到shared0_new和shared2,然后在shared0_new上删除mod(mobile_app_id,4)=2的数据,在shared2上删除mod(mobile_app_id,4)=0的数据,删除操作完成后shared0_new、shared2与shared0做同步,同步删除操作执行过程中的数据增量。同步追上之后,切换amoeba的路由规则,然后下线shared0。这种方式问题很多,首先时耗很高很高,delete完了之后并不能释放存储空间,还要optimize table,同样也是一个漫长的过程。针对大表的delete会产生一个很大的transaction,会在系统表空间中申请很大一块undo,delete完成后事务提交。这个undo空间并不会释放,而是直接给其他事务复用,这无疑会浪费很多存储空间。

       后来我们想到一个便捷的办法,就是利用mysqldump的—where参数,在备份数据的时候加一个mod(mobile_app_id,4)=2的参数,就可以单独备份出余数为2的数据,然后拿这个逻辑备份恢复到shared2上去,高效且优雅。

数据倾斜

       MySQL分布式存储不可避免的一个问题就是数据倾斜。业务在运行一段时间之后,会发现少部分shared数据增量特别快,原因是该shared上面部分用户的数据量较大。对于数据倾斜问题我们目前的措施是将这些shared迁移到1TB存储上来,但这并非长久之计。因此我们目前正在做一些新的尝试,比如对Amoeba做了一下扩展,扩展后的Amoeba支持将某一个mobile_app_id的数据单独指向后端一个shared节点组,即一个shared只存放一个用户的数据,同时采用ToKuDB存储引擎来存储这部分数据,ToKuDB能够对数据进行有效的压缩,除了查询性能稍有损耗之外,基本具备InnoDB引擎所拥有的特点,而且在线表结构变更比InnoDB快好几倍不止。这些测试基本已经进入尾声,很快将会应用到生产环境。

分布式join

       分布式join在业界仍没有完美的解决方案,好在听云业务在设计之初就从业务上避免了多表的join,在业务库中,报表中的每个纬度都会有一张表与之对应,因此查询某个纬度直接就会查询后端的某张表,都是在每张表上做一些操作。目前比较流行的分布式join的解决方案主要有两种:

       1、全局表的形式。举个栗子,A表 join B表,B表分布式存储在多个shared上,如果A表比较小,可以在所有的shared上都存一份A表的全量数据。那么就可以很高效的做join。看起来很美好,但是限制很多,应用的场景也很有限。

       2、E-R形式。举个栗子,用户表user(id,name)和订单表order(id,uid,detail),按用户id分片,order表的uid引用自user表的id。存放订单时,首先确定该订单对应用户所在的shared,然后将订单记录插入到用户所在的shared上去,这样检索某个用户所有的订单时,就可以避免跨库join低效的操作。

       目前的开源中间件中,MyCat对分布式join处理的是比较细腻的。阿里的DRDS对于分布式join的处理也是这样的思路。

MySQL擅长什么

       任何一种工具可能都只是解决某一个领域的问题,肯定不是放之四海而皆准的。正确的使用方式是让工具做自己擅长的事情。关系型数据库擅长的是结构化的查询,本身并不擅长巨量数据的清洗。我们在出2015年度APP行业均值数据报表时,需要将后端所有shared上的相关数据汇总起来然后做进一步的分析,这些数据最终汇总在5张表中,每张表都有几亿条的记录。然后对5、6个字段group by之后取某些指标的 sum值,最初尝试在MySQL中处理这些数据,MySQL实例给出24GB的内存,结果OOM了好几次也没有出结果。最后把数据拉到了hadoop集群上,使用impala引擎来汇总数据,处理最大的表近7亿条记录,9min左右出结果。所以,不要有all  in  one的想法,要让系统中的每个组件做自己擅长的事情。

分布式MySQL架构下的运维

       MySQL分布式虽然解决了存储和性能问题,但是在运维支持过程中却带来了一些痛点。

       1、跨分片统计数据。中间件是无法对后端的全量数据做查询的,类似年度APP行业均值报表这样的跨分片的全量数据的查询,只能使用自动化脚本从后端逐个shared上提取数据,最终再汇总。

       2、DML。经常会有变更表结构的需求,这样的操作大部分中间件是支持不了的,如果只有一个库好说,当后端几十个shared时,就比较头疼了,目前我们并没有很好的处理办法,只能使用自动化脚本批量到后端shared上执行命令,执行完成后,运行一个校验的脚本,人工核对校验脚本的输出内容。

       应对这样的情景,发型必然会稍显凌乱,但是目前仍旧很无奈,有必要重新设计一下我们的脚本,写一个输出更加友好,完全自动化的工具出来。

 

原文链接:http://blog.tingyun.com/web/article/detail/386

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
11天前
|
存储 关系型数据库 MySQL
【告别容量焦虑】RDS MySQL高性能本地盘全规格最大存储空间提升,最高可达16TB!
RDS MySQL存储能力狂飙升级,高性能本地盘全规格最大存储空间提升,最高可达16TB!这波升级,值得一试!
|
13天前
|
关系型数据库 MySQL Linux
在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾
以上就是在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾的步骤。这个过程就像是一场接力赛,数据从MySQL数据库中接力棒一样传递到备份文件,再从备份文件传递到其他服务器,最后再传递回MySQL数据库。这样,即使在灾难发生时,我们也可以快速恢复数据,保证业务的正常运行。
87 28
|
1月前
|
存储 SQL 关系型数据库
【YashanDB知识库】MySQL迁移至崖山char类型数据自动补空格问题
**简介**:在MySQL迁移到崖山环境时,若字段类型为char(2),而应用存储的数据仅为'0'或'1',查询时崖山会自动补空格。原因是mysql的sql_mode可能启用了PAD_CHAR_TO_FULL_LENGTH模式,导致保留CHAR类型尾随空格。解决方法是与应用确认数据需求,可将崖山环境中的char类型改为varchar类型以规避补空格问题,适用于所有版本。
|
1月前
|
SQL 关系型数据库 MySQL
【YashanDB知识库】字符集latin1的MySQL中文数据如何迁移到YashanDB
本文探讨了在使用YMP 23.2.1.3迁移MySQL Server字符集为latin1的中文数据至YashanDB时出现乱码的问题。问题根源在于MySQL latin1字符集存放的是实际utf8编码的数据,而YMP尚未支持此类场景。文章提供了两种解决方法:一是通过DBeaver直接迁移表数据;二是将MySQL表数据转换为Insert语句后手动插入YashanDB。同时指出,这两种方法适合单张表迁移,多表迁移可能存在兼容性问题,建议对问题表单独处理。
【YashanDB知识库】字符集latin1的MySQL中文数据如何迁移到YashanDB
|
1月前
|
缓存 NoSQL 关系型数据库
Redis和Mysql如何保证数据⼀致?
1. 先更新Mysql,再更新Redis,如果更新Redis失败,可能仍然不⼀致 2. 先删除Redis缓存数据,再更新Mysql,再次查询的时候在将数据添加到缓存中 这种⽅案能解决1 ⽅案的问题,但是在⾼并发下性能较低,⽽且仍然会出现数据不⼀致的问题,⽐如线程1删除了 Redis缓存数据,正在更新Mysql,此时另外⼀个查询再查询,那么就会把Mysql中⽼数据⼜查到 Redis中 1. 使用MQ异步同步, 保证数据的最终一致性 我们项目中会根据业务情况 , 使用不同的方案来解决Redis和Mysql的一致性问题 : 1. 对于一些一致性要求不高的场景 , 不做处理例如 : 用户行为数据 ,
|
2月前
|
Java 关系型数据库 MySQL
SpringBoot 通过集成 Flink CDC 来实时追踪 MySql 数据变动
通过详细的步骤和示例代码,您可以在 SpringBoot 项目中成功集成 Flink CDC,并实时追踪 MySQL 数据库的变动。
554 43
|
2月前
|
存储 SQL 关系型数据库
MySQL底层概述—4.InnoDB数据文件
本文介绍了InnoDB表空间文件结构及其组成部分,包括表空间、段、区、页和行。表空间是最高逻辑层,包含多个段;段由若干个区组成,每个区包含64个连续的页,页用于存储多条行记录。文章还详细解析了Page结构,分为通用部分(文件头与文件尾)、数据记录部分和页目录部分。此外,文中探讨了行记录格式,包括四种行格式(Redundant、Compact、Dynamic和Compressed),重点介绍了Compact行记录格式及其溢出机制。最后,文章解释了不同行格式的特点及应用场景,帮助理解InnoDB存储引擎的工作原理。
MySQL底层概述—4.InnoDB数据文件
|
2月前
|
SQL 关系型数据库 MySQL
基于SQL Server / MySQL进行百万条数据过滤优化方案
对百万级别数据进行高效过滤查询,需要综合使用索引、查询优化、表分区、统计信息和视图等技术手段。通过合理的数据库设计和查询优化,可以显著提升查询性能,确保系统的高效稳定运行。
88 9
|
2月前
|
监控 关系型数据库 MySQL
MySQL和SQLSugar百万条数据查询分页优化
在面对百万条数据的查询时,优化MySQL和SQLSugar的分页性能是非常重要的。通过合理使用索引、调整查询语句、使用缓存以及采用高效的分页策略,可以显著提高查询效率。本文介绍的技巧和方法,可以为开发人员在数据处理和查询优化中提供有效的指导,提升系统的性能和用户体验。掌握这些技巧后,您可以在处理海量数据时更加游刃有余。
261 9
|
2月前
|
存储 关系型数据库 MySQL
MySQL进阶突击系列(09)数据磁盘存储模型 | 一行数据怎么存?
文中详细介绍了MySQL数据库中一行数据在磁盘上的存储机制,包括表空间、段、区、页和行的具体结构,以及如何设计和优化行数据存储以提高性能。
下一篇
oss创建bucket