共计 4721 个字符,预计需要花费 12 分钟才能阅读完成。
一、写在结尾
vivo 云服务提供给用户备份手机上的联系人、短信、便签、书签等数据的能力,底层存储采纳 MySQL 数据库进行数据存储。
随着 vivo 云服务业务倒退,云服务用户量增长迅速,存储在云端的数据量越来越大,海量数据给后端存储带来了微小的挑战。云服务业务这几年最大的痛点,就是如何解决用户海量数据的存储问题。
二、面临挑战
2017-2018 年,云服务产品外围指标着重于晋升用户量。云服务在产品策略上做了重大调整,用户登录 vivo 账号后默认开启云服务数据同步开关。
此产品策略给云服务用户量带来了爆发式的增长,用户量从百万级别间接跳跃至千万级别,后端存储的数据量也从百亿级别飞跃至千亿级别。
为了解决海量数据的存储问题,云服务将分库分表的 4 板斧:程度分表、垂直分表、程度分库、垂直分库,全副进行了实际。
1、程度分表
荆棘之路 1:浏览器书签、便签单库单表,单表数据量已过亿级怎么办?
置信理解过分库分表常识体系的兄弟很快可能答复:单表数据量过大那就进行分表。咱们也是如此做的,将浏览器书签、便签模块单表拆分至 100 张表。
将浏览器书签、便签单表 亿级 数据量迁徙至 100 张分表里,每张表承载 1000W 的数据量。
这就是大家相熟的第一板斧:程度分表。
2、程度分库
荆棘之路 2:联系人、短信数据已分表,然而最后只分了 50 张表,未进行分库。用户量爆发式增长后,单库联系人总数据量已达到 几十亿,单表数据量已高达 5000W , 持续增长将重大影响 mysql 性能,怎么办?
第二板斧,程度分库 :1 个库撑持不住,那就多分几个库。咱们 将原来单库拆分成 10 个库,并且将原来单库联系人、短信 50 张表扩大至 100 张表,同样期间进行了几十亿存量数据的迁徙重路由,非常苦楚。
3、垂直分库、垂直分表
荆棘之路 3:最后云服务各个模块的数据存储都繁杂在一起。
当空间存在瓶颈后,咱们对各模块数据的存储空间散布进行了剖析,状况如下:
单库磁盘容量 5T, 联系人数据 占用存储空间 2.75T(55%), 短信数据 占用存储空间 1T(20%), 其余所有模块数据 共占用存储空间 500G(5%), 残余可用空间 1T,联系人、短信数据即占用了总空间的75%。
残余 1T 的空间容量是无奈撑持用户数据的持续增长, 状况不容乐观。若空间有余,所有模块都会因为空间问题导致不可用,怎么办?
(下图为云服务过后的数据存储空间分布图)
第三、四板斧,垂直分库、垂直分表:咱们将联系人数据、短信数据和其余模块数据进行存储解耦。将联系人数据、短信数据都独自拆分成库。
至此,云服务将分库分表的 4 板斧全副实际了一遍,数据该拆的拆,该分的分。
4、基于路由表的动静扩容计划
荆棘之路 4:从上述形容得悉拆分进去的联系人数据库采纳固定 10 个库的分库策略,后期评估 10 库 *100 张表是能够满足业务数据增长需要的,本认为能够居安思危,然而联系人数据增长速率超出了预期。
联系人数据库独自拆分 9 个月 之后,单个库的存储空间 从 35% 增长至 65%。依照这个增长速度,再撑持 6 个月,独立拆分进去的联系人数据库将再次面临空间有余问题。
如何解决?持续扩容是必定的,外围点在于采纳哪种扩容策略。如果采纳惯例的扩容计划,那咱们将面临着海量存量数据的迁徙从新路由问题,老本太大。
通过技术组沟通探讨,联合云服务联系人业务的本身个性(老用户的联系人数量基本上是稳固的,不会频繁的增加大量的联系人, 老用户联系人数据增长的速率可控),咱们最终采纳了基于路由表的动静扩容计划。
以下介绍下此计划特点:
- 增加用户路由表,记录用户联系人数据具体路由在哪个库,哪张表;
- 新用户的联系人数据会路由到新扩容的数据库里,不会对原有老库造成数据存储压力。
- 老用户的数据不会动,还是保留在原来的数据库。
- 此计划的特点是保障了原有老库只需保障老用户的数据增长即可,新用户全副由新扩容的库来承载。
老用户联系人的增长速率尽管可控,但咱们冀望 原老库能预留 60% 的存储空间来撑持老用户的数据增长。目前老库只残余 35% 的可用空间,不合乎咱们的要求。
为了升高老库数据占用的存储空间,自然而然咱们想到了从 数据压缩 层面着手。
三、压缩计划预研
云服务对数据库数据压缩进行了以下 3 种计划的预研:
计划 1:程序自行实现数据压缩,压缩后再保留至数据库
劣势:
无需对数据库进行任何革新,批改齐全由程序本人收敛,能够自在管制须要进行压缩的字段。
劣势:
存量数据须要开发额定的压缩工作进行数据压缩,且存量数据量级过大,靠程序进行数据压缩耗时不可控。
数据压缩入库后,须要从 db 平台间接进行 select 查问字段的内容不再是可读的,加大了后续定位问题的难度。
计划 2:MySQL 数据库 InnoDB 自带的数据压缩能力
劣势:
利用 InnoDB 已有的能力进行数据压缩,对于下层程序无需做任何革新,且不影响后续 select 数据查问。
劣势:
实用于数据量较大,读多写少的业务场景,且对要求高查问性能的业务不太适合。
计划 3:切换 InnoDB 存储引擎至 TokuDB,利用 TokuDB 引擎人造的数据压缩能力
劣势:
TokuDB 人造反对数据压缩,并且反对多种压缩算法,反对频繁的数据写入场景,对于大数据量的存储有人造的劣势。
劣势:
MySQL 须要装置额定的插件对 TokuDB 引擎进行反对,且公司目前没有业务有 TokuDB 成熟的应用教训,接入后的危险未知,对后续 DBA 的保护也是一项挑战。
咱们通过综合思考,最终决定采纳第二种压缩计划:InnoDB 自有的压缩能力。
次要起因有以下几点:
- 操作简略:由 dba 更改现有 innodb 数据表的文件格式,即可对数据进行压缩;
- 压缩速度可控:通过测试,1 张 2000W 的数据表,通过此形式,1- 2 天内即可实现整张表的数据压缩;
- 革新成本低:整个革新过程只须要 dba 执行相干 SQL,更改数据表的文件格式,下层的程序代码无需做任何改变;
- 比拟适宜云服务的业务场景:用户数据备份、复原,都不属于高性能、高 QPS 的业务场景,且云服务的数据表大多合乎存在大量字符串字段的特色,非常适合进行数据压缩。
四、压缩计划验证
1、InnoDB 压缩能力介绍
MySQL 5.1.38 版本之前只有 innodb-base 的存储引擎,默认文件格式为 Antelope, 此文件格式反对 2 种行格局(ROW_FORMAT):COMPACT 和 REDUNDANT,这 2 种都不是数据压缩类型的行格局。
MySQL 5.1.38 后引入 innodb-plugin,同时引入了 Barracude 类型的文件格式。Barracude 齐全兼容 Antelope 的文件格式,同时反对另外 2 种行格局 DYNAMIC、COMPRESSED(反对数据压缩)。
2、压缩环境筹备
批改数据库配置:更改数据库的文件格式,默认为 Antelope,批改为 Barracuda
SET GLOBAL innodb\_file\_format=Barracuda;
SET GLOBAL innodb\_file\_format_max=Barracuda;
SET GLOBAL innodb\_file\_per_table=1
阐明:innodb\_file\_per_table 必须设置为 1。起因是在 InnoDB 零碎表空间是无奈进行压缩的。零碎表空间不仅蕴含用户数据,还蕴含 InnoDB 外部零碎信息,永远不能被压缩,所以须要设置不同表不同的表空间来反对压缩。
设置 OK 后能够执行 SHOW GLOBAL VARIABLES LIKE‘%file\_format%’及 SHOW GLOBAL VARIABLES LIKE‘%file\_per%’确认批改是否失效。
(此种设置形式只对以后会话失效,mysql 实例重启后会生效。若须要永恒失效,请在 mysql 全局配置文件里配置)
3、压缩成果测试验证
筹备 1 张反对压缩格局的数据表,1 张不反对压缩的数据表,字段格局全副一样。
压缩表:
阐明:row\_format=compressed, 指定行格局为 compressed。举荐 key\_block\_size=8。key\_block_size 默认为 16,可选值有 16、8、4 代表的是 InnoDB 数据页大小,值越小压缩力度越大。基于 CPU、压缩率综合思考,线上举荐设置为 8。
非压缩表:
筹备数据:应用存储过程同时向 t\_nocompress 表和 t\_compress 表插入 10W 条雷同的数据。2 张表占用空间大小如下图:
t\_compress 表数据占用 10M,t\_nocompress 表数据占用 20M,压缩率 50%。
阐明:压缩成果取决于表的字段的类型,典型数据通常具备反复值,因而可能无效压缩。CHAR,VARCHAR,TEXT、BLOB 这类。
字符串类型的数据通常可能很好地压缩。而二进制数据 (整数或浮点数字)、曾经通过压缩的数据(JPEG 或 PNG 图像) 通常起不到压缩成果。
五、线上实际
从上述测试验证来看,压缩率若能达到 50%,那么联系人老库占用空间从 65% 压缩至 33%,预留 60% 的残余空间是可能达成的。
然而对线上的数据咱们须要放弃敬畏之心,线上实际之前,须要线下先进行计划验证,同时咱们还须要思考以下问题:
1、数据压缩,解压操作是否对 db 服务器的性能造成影响?
咱们采纳性能压测的形式来评估压缩前后对数据库服务器 CPU 的影响。以下是压缩前后 db 服务器的 CPU 比照图:
联系人单表数据量已有 2000W 的前提下,对此表进行数据插入。
压缩前:一次性插入 50 个联系人,并发量 200,继续 10 分钟,TPS 150,CPU33%
压缩后:一次性插入 50 个联系人,并发量 200,继续 10 分钟,TPS 140,CPU43%
数据表压缩后,频繁数据插入数据库 CPU 的确会增高,然而 TPS 未受太大影响。通过重复压测,数据库服务器 CPU 根本稳固在 40% 左右,是业务能够承受的范畴。
2、变更数据表文件格式是否会对业务 SQL 读写造成影响,影响失常的业务性能?
咱们次要做了 线下验证 和线上验证:
线下验证:测试环境将联系人数据表全副调整为压缩格局,安顿测试工程师帮助点检了联系人的全量性能,最终性能全副失常。
预上线环境依照测试环境的步骤再走一遍,性能点检无异样。
线上验证:选取对于用户不敏感的通话记录模块的数据表进行压缩,抉择压缩 1 个库里的 1 张表,关注此张表的数据读写状况,注意用户投诉。
继续察看了 1 周后,此张表的通话记录数据能失常进行读写,期间未收到任何用户的异样反馈。
3、线上联系人联系人数据量宏大,怎么保障压缩时服务的稳固?
咱们次要是依照以下思路来进行衡量:
- 选取 1 张联系人数据表进行压缩,评估单张表破费的工夫。
- 抉择单库,进行多表并发压缩,察看 CPU 占用状况。DBA 衡量 CPU 最高值不能超过 55%,以这个规范逐步调整压缩并发数,保障 CPU 稳固在 55% 左右,最终失去单库最多反对多少张表同时进行压缩。
- 联合第一步和第二步咱们能够计算出所有库全副数据表压缩结束大抵破费的工夫,同步至项目组及相干责任人后,依照步骤施行压缩工作即可。
最终线上联系人数据库进行数据压缩的成果如下:
六、写在最初
本文介绍了云服务随着业务倒退,海量数据存储所带来的挑战,以及云服务在分库分表、数据库数据压缩上的一些教训,心愿能提供借鉴意义。
InnoDB 数据压缩实用于以下场景:
- 业务数据量较大,且数据库磁盘有空间压力的业务;
- 实用于读多写少的业务场景,对性能、QPS 有高要求的业务不太实用;
- 实用于业务数据表构造中存在大量字符串类型的数据,这种类型的数据表通常可能进行无效的压缩。
最初:
- 业务在分库分表选型时,肯定要做好数据量增长的充沛预估,后续数据库扩容带来的数据迁徙工作会伤筋动骨。
- 对线上数据要放弃敬畏之心,计划肯定是通过线下重复验证之后能力利用到线上。
作者:vivo 平台产品开发团队