一、历史数据库
MySQL 数据库可以很好地支撑海量的 OLTP(Online Transaction Processing)的系统,但是对于海量的互联网业务来说,数据量是非常巨大的。
假设一天 10 亿笔交易,每笔交易至少需要有一条记录,用于记录该笔交易,这就是通常所谓的流水数据。再假设一笔流水占用 1K 存储空间,那么每日流水占用存储空间 1000G,365 天就需要占用 365T 的存储空间。
即便我们做了分布式数据库架构,有 1000 个分片,每个分片 1 年的流水数据就需要 365G,这还不包括其他数据,仅仅只是一笔交易的流水。而线上的库表和业务就更为复杂了。
或许大家会问:为什么要存储 1 年以上的数据呢?超过一定期限删除不就可以了吗?大家想一想,我们的历史微博是不是都是能看的?我们的淘宝历史交易也都是能查询的?对于金融业务来说,每笔历史交易是不是也都可以可以回溯的?
所以,即便是历史的数据,也要求是可以查询的。所以,对于海量的互联网业务来说,除了线上的数据库,还需要有一套对应的历史数据库,用于查询历史的数据。
注意,我们这里谈论的历史数据库,不是用于数据分析的系统,而仅仅是一个历史查询数据库。
整理了一份面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记的【点击此处即可】即可免费获取
二、历史数据库架构
从架构角度看,线上数据库系统与历史数据库系统的架构如下图所示:
可以看到,业务会将最新的数据变更插入在线的 MySQL 数据库,但 MySQL 数据库仅保留最近半年的数据,超过半年的数据会存放在历史数据库系统中。对于历史数据库的选型来说,一般可以是(分布式)MySQL 数据库、HBase、ElasticSearch。
历史数据库是 MySQL,那么基本和线上架构一致,只是存储的容量会更大。但缺点是,即便使用分布式架构,数据节点的扩容需要搬迁数据,这部分工作相对比较麻烦一些。
HBase 是 Hadoop 生态的大数据系统,是一个 KV 系统,非常适合进行点查询,其对于数据的扩容也是非常容易。但是它的缺点是不支持事务,没有二级索引,所以在使用时会有诸多限制,比如二级索引需要自己创建索引表,索引表和主表的数据一致性有可能会存在问题。
ElasticSearch 是文档数据库,其他特性与 HBase 类似,支持数据节点动态的扩缩容,查询支持也更为丰富一些。历史数据库的选型需要结合业务具体分析,通常个人更倾向于使用 ElasticSearch,简单易用。
三、数据迁移系统
简单来说,迁移系统需要做以下两件事情:
- 1、将线上数据尽可能地准实时同步到历史数据;
- 2、清理线上数据库系统,仅保留最近一段时间的数据,如半年的数据。
这时,整体的数据库系统架构如下图所示:
DTS 是 Data Transfer Service,数据迁移服务,负责将在线数据准实时地同步到历史数据库。
DTS 的实现原理是订阅 MySQL 的二进制日志变化,将数据库的变更同步到历史数据库。虽然原理并不复杂,但是由于是异构数据库系统,在数据消费这里还需要做不少的工作。此外,要做到准实时要求,如仅 30 秒内的延迟,对于 DTS 也是一种考验。
业界的 DTS 有 Maxwell、Canal。但通常这些 DTS 仅负责订阅二进制日志,消费需要用户自己实现存储到不同的数据库。
DAS 是 Data Archive Service,数据归档服务,负责清理超过一定时间的线上数据,同时需要确保清理的数据都已经在历史数据库中。所以,DAS 又需要做两件事情:
-
1、获取超过某个阈值的数据,确保这些数据都已经在历史数据库中;
-
2、根据调度,在非业务高峰期,从 MySQL 数据库中删除超过某个阈值的数据。
由于在前面的库表结构设计中,要求每张业务核心表都要有一个最后修改时间的字段,因此那些数据已经超过某一时间点,如半年,是比较容易知道的。然后,再进行线上数据与历史数据库的核对即可。
第二个步骤会真实删除线上数据库中的数据,风险较高,但通过多次数据校验和逻辑判断,DAS 可以确保删除数据的正确性,从而正确删除超过阈值的数据。
同时,为了不影响删除时对于业务的影响,DAS 还需要做调度,删除是小批量的,并且是在非业务高峰期执行的操作。