前言
随着业务的快速发展,数据库已经有了上亿条记录,数据存储达到了上百G,原有的单库单表设计已经无法支持系统的稳定性以及接口的响应速度了,数据库存在大量慢查询,且需要提供对C端这种大访问量场景提供支持。
数据库随时面临着宕机的风险
,基于此,决定对大表进行治理,下面是对大表改造的一些通用方案实践总结
现状
DMS单表信息383,997,734条记录的大表,日增量接近70W
DMS子表信息347,966,131记录的关联表,日增量超过70W
上面第一张表是存储主用户数据的主表,日增量70万左右,第二张表是第一张表的关联表,为1:N的关系,目前已经有213.12GB的容量了,持续增长下去会严重影响系统的稳定性
分库分表技术选型
TDDL
- 优势:淘宝的分库分表中间件,基于JDBC规范,没有server,用client-jar包依赖的方式部署
- 劣势:不支持join语句,not语句,for update,force index语句,多表查询,between/and等,且github上TDDL现在已经停止维护了
kingshard
- 优势:拆分表的数量可以跟拆分库的数量不一样,即分库后可以建子表,目前快手在用
- 劣势:kingshard由go语言开发,使用时需要安装go语言环境和server,不支持各类join和多表查询, github活跃度不够
MongoDB
- 优势:MongoDB的分片功能从并发性和数据量这两个角度已经能满足大数据量的需求
- 劣势:MongoDB不是关系型数据库而是文档型数据库,它的每一行记录都是一个结构灵活可变的JSON。如果存储非常重要的订单数据时,我们就不能使用MongoDB,因为订单数据必须使用强约束的关系型数据库进行存储。事务、锁、复杂SQL支持度不够,遇到问题不好处理,且公司运维能力和稳定性方面得不到保障
TiDB
- 优势:支持大数据量处理的需求
- 劣势:运维能力不足,稳定性和功能扩展性得不到保障
Mycat
- 优势:非常成熟的一款中间件,需要部署server做代理,对研发无感知,支持事务,跨语言,目前京东有在用
- 劣势:因为有中间代理层,性能不是很好且github活跃度不够
ShardingSphere
- 优势:前身sharding-jdbc,目前比较热的一款中间件,很多互联网公司在使用,支持分布式事务,社区活跃度高,有问题可以很快得到反馈
- 劣势:不支持存储过程,函数,游标的操作,不支持 JDBC 4.1 接口新功能
综合市面上现有的成熟大表治理技术,最终采用了Apache ShardingSphere来治理大表,对大表进行水平分片
分库分表的大小评估
目标表现存数据量:3.8亿
日新增数据:70W(随着业务增加,数据可能增加)
年新增数据:70W * 30 * 12 = 2.5亿
5年后数据总量:16.3亿
大表拆分为几个库,每个库拆分成多少表应根据以上关键指标进行合理评估,拆分的库表太小了,则拆分后每个库表也容易变为大表,拆分的太大了,服务器,数据库成本又太高。
所以综合以上数据采用32个库x8张表进行分库分表,5年后每张表平均数据量为:636W
单表数据量不超过千万,查询性能在当前机器配置下可以接受,如果未来数据过多,可以根据数据创建时间根据年限进行归档处理,保留最近5年用户最新数据,做冷热分离改造
大表改造的基本步骤
1.上线双写以及数据迁移,数据对比程序,此时业务还是读取旧库
2.双写读旧:切换apollo之类的开关(apollo对应配置)以及记录双写开始时原数据库的最大主键ID及上线双写时间,方便后续数据迁移
3.数据迁移:开启定时任务,在夜间访问低峰期分页迁移历史数据(ID小于双写时记录的最大主键ID的数据)
4.数据对比:等所有历史数据迁移完成,校验历史数据是否全部迁移完成。可以采用
分页对比,抽样对比,中断对比后重新对比
(模拟发布重启时的异常情况)
5.双写读新:修改读写策略为双写读新库 观察切换读取新库一段时间(具体时长待定),若没有问题则修改读写策略为读写新库策略,若观察到日志异常或用户反馈则切回旧库,问题解决后再观察一段时间
6.写新读新:日志观察没问题,也没有异常反馈时,切换数据库的访问读写均为新库,完成大表改造
7.数据清理:针对老表的历史数据进行归档清理
异构数据查询
上面是只有C端用户访问的一些通用大表治理方法,但实际上除了C端用户(点查)还有有B端运营的数据统计分析,方便售后,促销等(范围查询),但分片键是以用户维度确定的,B端用户无法进行分片查询,这时需要引入ES将原数据中的索引信息实时同步到ES中。对于B端的访问,先查询ES中的索引信息,再根据ES中的信息点查数据库中的信息做聚合。
总结
提升系统稳定性:大表对于数据库吞吐能力的影响以及数据治理的风险都在增加,大表治理工作对系统稳定性的提升有很大的好处。
增强用户体验:在单表架构下,数据查询复杂度高,会影响数据库响应时间以及吞吐量。分库分表之后会有效提升数据库的核心指标,进而提升C端链路的请求时效,从而提升用户体验。
降低运维成本:大表治理的核心成本在运维成本,针对于任何大表的DDL、重建操作都会有影响,风险随着数据量正比提升。大表拆分之后,针对每个sharding表的数据量都有降低10倍以上,有效降低运维成本。