分表分库
背景
一般地说,系统达到一定规模之后,必然带来数据量的大幅增加,同时数据库压力会越来越大,各种查询,各种统计需求不断涌来,此时单库已经很难满足
业务上的需要了,分表分库在所难免。如何分表分库是一门学问,也是一门艺术,学会它不容易。
影响
分表分库带来的好处自不必多说,我们今天来讨论一下分表分库带来的一些负面影响。
首先数据库一旦拆分,势必对DAO层的代码有影响,原本直接向某一台数据库发送SQL命令就可以了,分表分库之后,数据该去哪个库查询就成了一个问题。所以查询落在哪个库上是第一个问题。
接着就是性能,如果数据是分布在若干个数据库上的,需求又希望统计所有的信息,那么此时必须要从所有的库中取数据才能完成计算任务,所以性能如果保证是第二个问题。
最后数据一致性如果保证,这个问题涉及的面比较广,在今天这篇博客中我不讨论。
策略
分表分库这种事情空说没有意义,因为它是需要根据业务场景进行分析,世上不存在一个通用的分表分库方案,所以我拿我做的一个项目作为例子来说一说。
我做的项目是一个跑步软件,后台数据库有一个跑步表,其中的每一行记录保存了一次跑步的详细信息,比如跑步时长、跑步距离等。
第一种策略:根据UserID作为分片键,将数据分散到多个库中。
这种策略其实很不好,因为面试官会接着问你,如果有一个人的跑步次数非常多,大大超过了其他学生导致数据倾斜,你会怎么处理?我们实际运行的系统由于存在一些缺陷,
被一些不法分子用脚本的方式刷跑步记录,一个人的跑步记录可以一次刷上万条,所以这种数据倾斜的情况必须要考虑进去,但是因为通过UserID来分库,一个人的跑步记录只会落
在一个库上,所以该策略不太可行。
第二种策略:根据UserID和跑步时间组合起来作为分片键,进行范围分片
这种策略继承了第一种策略的优点,即不同跑步者的跑步数据可以分散到多个库中,同时这种策略还带来一个好处,同一个人的跑步数据能根据时间进一步分散到多个DB上
如果我们将所有的库逻辑上围成一个圈,这意味着最后一个库和第一个库逻辑上是紧挨着的。
以分2个库为例,先通过UserID取余确定哪一个库作为第一个库,1天的秒数是86400秒,跑步时间(秒为单位)对86400取余,0-43200落在第一个库,43201-86400落在第二个库,这样可以做到范围分片。
于是我们解决了数据倾斜的问题。