亿级大表分库分表实战总结( 二 )


以下举一些思考点 。
1)哪些查询是无法拆分的?例如分页(尽可能地改造 , 实在改不了只能以冗余列的形式)
2)哪些查询是可以业务上join拆分的?
3)哪些表/字段是可以融合的?
4)哪些字段需要冗余?
5)哪些字段可以直接废弃了?
6)根据业务具体场景和sql整体统计 , 识别关键的分表键 。其余查询走搜索平台 。
思考后得到一个查询改造总体思路和方案 。
同时在本项目中需要将两张表融合为一张表 , 废弃冗余字段和无效字段 。
2.4 新表设计这一步基于2.3对于查询的拆分分析 , 得出旧表融合、冗余、废弃字段的结果 , 设计新表的字段 。
产出新表设计结构后 , 必须发给各个相关业务方进行review , 并保证所有业务方都通过该表的设计 。有必要的话可以进行一次线下review 。
如果新表的过程中 , 对部分字段进行了废弃 , 必须通知所有业务方进行确认 。
对于新表的设计 , 除了字段的梳理 , 也需要根据具体查询 , 重新设计、优化索引 。
2.5 第一次升级新表设计完成后 , 先做一次jar包内sql查询的改造 , 将旧的字段全部更新为新表的字段 。
此处为2.0.0-SNAPSHOT版本 。
然后让所有服务升级jar包版本 , 以此来保证这些废弃字段确实是不使用了 , 新的表结构字段能够完全覆盖过去的业务场景 。
特别注意的是 , 由于涉及服务众多 , 可以将服务按照 非核心 与 核心 区分 , 然后分批次上线 , 避免出现问题导致严重故障或者大范围回滚 。
 
2.5 最佳实践2.6.1 尽量不改变原表的字段名称在做新表融合的时候 , 一开始只是简单归并表A 和 表B的表 , 因此很多字段名相同的字段做了重命名 。
后来字段精简过程中 , 删除了很多重复字段 , 但是没有将重命名的字段改回来 。
导致后期上线的过程中 , 不可避免地需要业务方进行重构字段名 。
因此 , 新表设计的时候 , 除非必不得已 , 不要修改原表的字段名称!
2.6.2 新表的索引需要仔细斟酌新表的索引不能简单照搬旧表 , 而是需要根据查询拆分分析后 , 重新设计 。
尤其是一些字段的融合后 , 可能可以归并一些索引 , 或者设计一些更高性能的索引 。
2.6 本章小结至此 , 分库分表的第一阶段告一段落 。这一阶段所需时间 , 完全取决于具体业务 , 如果是一个历史包袱沉重的业务 , 那可能需要花费几个月甚至半年的时间才能完成 。
这一阶段的完成质量非常重要 , 否则可能导致项目后期需要重建表结构、重新全量数据 。

这里再次说明 , 对于微服务划分比较合理的服务 , 分库分表行为一般只需要关注存储架构的变化 , 或者只需要在个别应用上进行业务改造即可 , 一般不需要着重考虑“业务重构” 这一阶段 。
 
3.第二阶段:存储架构设计(核心)对于任何分库分表的项目 , 存储架构的设计都是最核心的部分!
3.1 整体架构根据第一阶段整理的查询梳理结果 , 我们总结了这样的查询规律 。
  • 80%以上的查询都是通过或者带有字段pk1、字段pk2、字段pk3这三个维度进行查询的 , 其中pk1和pk2由于历史原因存在一一对应的关系
  • 20%的查询千奇百怪 , 包括模糊查询、其他字段查询等等
因此 , 我们设计了如下的整体架构 , 引入了数据库中间件、数据同步工具、搜索引擎(阿里云opensearch/ES)等 。
下文的论述都是围绕这个架构来展开的 。
亿级大表分库分表实战总结

文章插图
 
3.1.1 mysql分表存储Mysql分表的维度是根据查询拆分分析的结果确定的 。
我们发现pk1pk2pk3可以覆盖80%以上的主要查询 。让这些查询根据分表键直接走mysql数据库即可 。
原则上一般最多维护一个分表的全量数据 , 因为过多的全量数据会造成存储的浪费、数据同步的额外开销、更多的不稳定性、不易扩展等问题 。
但是由于本项目pk1和pk3的查询语句都对实时性有比较高的要求 , 因此 , 维护了pk1和pk3作为分表键的两份全量数据 。


推荐阅读