记一次数据库冷热分离

前言

最近在一家小公司实习,文章也没怎么更新。前两天参与了后台系统数据库冷热分离(一期)的工做,虽然只是参与了定时任务和接口的开发改造,但仍是想了解一下它的来龙去脉,毕竟做为一只咸鱼,就要有翻身以后再做咸鱼的觉悟,因而就有了这篇文章。html

先说一下背景吧,随着业务的发展,生产库中订单等数据已经有数千万,而相似订单详情、结算详情的数据则已通过亿,而且天天以 20w+ 的数据在增长,能够说对数据库的改造已是迫在眉睫了。前端

解决方案

考虑到具体的业务须要,按照用户的习惯,通常在近期的订单、订单详情等数据,因为有待评价、售后等问题,访问会比较多,这些数据就称之为热数据;数据库

而对于较早时间的订单、订单详情等数据,通常都是已评价、已完成售后等状态,用户通常不会常常访问,这些数据就称之为冷数据。分布式

因此考虑是否可以进行冷热分离。对于须要常常查询的数据放在生产库中,例如一个月以内的数据;而那些查询很少的数据,例如一个月以前的数据,将其迁移到历史库中。这样既能够减轻生产库的压力,也能够保持数据的完整。性能

如何迁移

定好大体方案后,就要考虑如何对数据进行迁移了。因为数据量过大,迁移不可能一次并在短期内就完成。学习

对于之前的数据,考虑在凌晨分批次进行迁移。因为不一样时期的数据量不一样,定时任务很差实现,只能经过手动查询,可能刚开始是好几个月的数据一块儿迁移,到后面就是十几天的数据一块儿迁移。测试

这里经过人工去判断一段时间内的数据量,并进行迁移,主要就是为了保证迁移工做不能影响生产库的正常运行,另外也要让迁移次数较少,迁移工做尽早完成。设计

而对于之后的增量数据,则能够设置定时任务,每日凌晨自动执行,迁移一个月以前的数据。cdn

在迁移数据时,以订单为粒度进行迁移,其总体的逻辑主要分为如下几步:htm

  • 数据迁移工做:
    • 每次查询一部分数据(例如 500 条/1000条),判断其是否已经迁移过(额外一张表记录迁移状态),这主要是为了防止一次查询过多数据会影响生产库的运行;
    • 若是没有迁移过,则查询与该订单相关的数据,将其迁移到新库中,并更新迁移状态;
  • 测试检验工做:
  • 主库删除工做:在测试一段时间后,若是无误,则将主库中的已经迁移完成的数据删除,一样这里每次删除一部分数据。

读写设计

在数据迁移后,另外一个问题就是如何读写了,通常会有以下几种方案。

对于读操做,一种方案是,每次在查询时,优先查询热库,只有当结果没有命中,或只有部分命中时,才去查询冷库。这里为了区分所有命中和部分命中,能够在热库中建立一个表,记录每次要求查询冷库时的查询条件、查询的结果数量等。在查询热库时,若是相同查询条件的查询结果数量一致,则本地查询结束,不然就要到冷库中进行查询。

另外一种方案,则能够经过前端配合实现,每次查询时,默认只查询最近一段时间内的数据,也就是主库内的数据。若是用户须要查询之前的数据时,再去冷库中查询就行了。这也是目前我司的实现方案。

而对于写操做,也有两种方案。

一种是每次在存储数据时,在热库中存储一份,在冷库历史表中一样存储一份。而后每日凌晨经过定时任务删除一段时间以前的数据,若是数据量较大的话,能够按照区间进行删除,防止影响生产库的正常运行。

另外一种方案,与之相似,只不过在写操做时,只是在热库中进行存储。将数据从热库迁移到冷库的操做,放在凌晨的定时任务中执行。

扩展学习

其实通常来讲,单表数据量在数千万时,数据的写入和查询效率就会受到影响。这时就应该考虑进行分表,例如水平分表、垂直分表。

分表

对于水平分表,也有多种分表的策略。

按照范围划分

按照范围划分,例如将表中的数据按照时间,每月或每一个季度一张表。

这种作法也有利有弊:

  • 好处是能够很容易来控制单表的大小,自然扩展,数据量很大时只须要减少时间的粒度便可;
  • 缺点是对批量写入等操做的效率问题没有解决,仍是集中在一种表上。

按照 Hash 切分

按照 Hash 切分,通常使用 Mod 2^n 将数据划分到不一样的表中。

mod 的值选择为 2^n,具体根据业务决定,目标就是为了在之后的扩展时能尽可能少迁移,甚至不迁移数据。

这种作法若是划分均匀,批量写入、查询等操做均摊到各个表中,对性能不会有太大影响。可是须要对 mod 的值仔细权衡,方便之后的扩展。

分库

分表很大程度上解决了单表写入和查询的效率,但对于数据库而言,其负载压力并无变化,对于分库也有相似于分表的不少策略,这里就再也不多说了。

最后

分库分表虽然带来了很大的好处,但也有一些问题须要处理,除了读写设计外,还有分布式 id,分布式事务,动态扩容等问题等着咱们一个一个去挑战。活到老,学到老。

参考资料

相关文章
相关标签/搜索