一、业务背景
目前生产库数据库服务器数据存储达到了13T,其中license_spart表数据量达到了200亿,占用7.5T,空间占用率达到54%。而且这张表每年数据增长量达到30亿。其中有效VALID数据占20亿,无效数据INVALID占180亿。由于业务上有些场景,需要查询无效数据,所以不能直接删除。随着license_spart表规模持续扩大,会带来严重的性能问题、存储成本增加、备份与恢复困难、数据一致性问题(生产4台服务器)等等。
二、整体目标
将license_spart数据整体迁移到归档库,主库license_spart只保留最新的3个月的有效VALID数据,归档库按照年份保存有效和无效数据,实现主库license_spart存储大幅缩减。
二、治理策略
1、归档库按照年份创建数据表
整体采用分库分表方案,申请归档库数据库服务器资源,然后创建license_spart_2018到license_spart_2035这18张表。归档库表字段跟主库license_spart表字段高度保持一致。
2、分析数据量及规模,指定定时同步策略
分析主库license_spart表的日增长量达1000w(其中有效数据达20w),所以针对2025年以前的数据,采用【全量】+【实时】同步方式;针对2025年之后的数据,采用【实时】方式。
同步方式 | 定时任务名 | 源表 | 目标表 | 查询条件 |
---|---|---|---|---|
全量+实时 | license_spart_2018 | license_spart | license_spart_2008 | lsn < ‘LIC2019’ |
全量+实时 | license_spart_2019 | license_spart | license_spart_2019 | lsn like ‘LIC2019%’ |
… | … | … | … | … |
实时 | license_spart_2026 | license_spart | license_spart_2026 | lsn like ‘LIC2026%’ |
由于数据量比较大,可以在业务不繁忙时间(比如凌晨0点~5点),分100批次同步数据,每次同步5w数据,根据实际情况可以动态调整参数大小。
主库数据同步完成后,建议保留3~4个月时间(2个迭代版本),无问题,再清空生产主库无效数据。
3、编写读取归档库工具类
Spring框架中,Spring-JDBC模块提供了AbstractRoutingDataSource,其内部可以包含了多个DataSource,通过继承该类并覆盖determineCurrentLookupKey方法,可以根据业务需求动态选择数据源。利用AOP注解实现动态切换数据源,参考利用AOP实现数据库读写分离。
编写一个公共查询归档库Service方法,由于归档库跟主库物理分离,所以采用无事务方式,否则会不生效。lsn组成分为LIC+年份+XXXX+标识等构成,通过对lsn的前7位进行切分,能够找对对应的归档库。
@DataSource("archiving")
public List<String> getArchivingLsnList(List<String> lsnList){// 根据入参lsn进行切分...
}
这样在业务代码查询license_spart时候,如果返回lsnList结果为空,再利用getArchivingLsnList查询归档库数据,进行补充。
4、生产验证及回滚
生产上线后,验证同步的数据是否准确,业务逻辑查询和修改是否无误等。如果有问题,及时回滚。
5、定时任务删除生产库数据
编写定时任务定期清理2个月前的数据,利用相关同步工具每天进行物理删除2个月前的主库数据。
针对主库旧表数据清理,采用表重命名方式,进行替换,最后删除旧表。