`
无量
  • 浏览: 1133892 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

海量数据存储--分库分表策略详解

阅读更多
海量数据存储--分库分表策略详解

一、背景:
    系统刚开始的时候,数据库都是单库单表结构。随着业务量的增加进行第一次数据库升级,根据业务垂直拆分数据库,这样多变成多个业务数据库,每个数据库里面还是单表结构。接下来,继续随着业务量的继续增加,单表已经很难承受数据量,就要进行分表,这个时候就是,多个业务库,每个业务库下对需要分表的表进行分表。再接下来,随着应用的增加,数据库IO,磁盘等等都抗不住了,就要把分表的表分到多个库,这样就形成了如下的结构。



    重点:本文主要讨论的是分库分表的策略,也就是分库分表的规则或者说是算法。

二、分库分表的依据--分库分表字段的选择
    分库分表首先要确定根据哪个字段、或者哪几个字段进行路由,一般的原则是按使用频率最高维度的字段去分库分表,尽量保证高使用维度下只查询单表
    常用的字段有主键ID,用户ID,时间,商户ID,产品ID,业务类型等等


三、分库分表策略
主要原理:分区、取模、数据路由表

1. 按照时间区间
1)基本原理:
一定区间内时间产生的数据放到一张表里面,多个时间区间的表放到一个库里面

2)简单例子:
单库多表结构,按月分表可以这样,user_201601,user_201602,...,user_201612这种结构。按年分表可以这样,user_2016,user_2017,...这种。

3)多库多表算法:
比如按天分表,每天一张表,当单库超过100张表的时候,进行分库到下一张表。那么假如第一张报表在库BD0,表名是user_20160201。从DB0.user_20160201,..到DB0.user_20160511就100张表了,接下来就要进行分库了,进入20160512,就是DB1.user_20160512,这个算法就是上线的时候定一个上线日期,具体算法如下

库ID = (当前日期 - 上线日期)/ 100
表ID = user_yyyyMMdd
注:好处是可以直接根据时间经过简单计算定位到哪个库和哪个表


还有一种算法:
库ID = (当前日期 - 上线日期)/ 100
表ID = (当前日期 - 上线日期) % 100
表名如下: DB0.user_0001, user_0002,....,user_01000。
注:表名和库名都要经过计算,比较麻烦


4)按月分表,每个月一张表;这种情况,一般就不用分库了,一年12张表说明量也不会特别大,如果量特别大,或者是热点数据,可以一年分一个库,具体算法和上面差不多。

5)按季度分表,基本不用分库。
6)按年分表,肯定不用分库了,没有必要了。

2. 按照主键ID区间
对于自增的主键ID,可以按照ID区间进行分表,以1000万数据量为分界线,对线性的ID进行切割分表,每涨到1000万数据,分到下一张表,超过一定数目的表,进行分库。

库ID = 主键ID / 1000万 / 100
表ID = 主键ID / 1000万 % 100
如:DB0.user_0000,...,DB0.user_0099, DB1.user_0000,...,DB1.user_0099


3. 按照指定字段hash后再取模
如果要取模的字段不是整数型,要先hash后,再通过取模算法,算出在哪个库和那个表。具体算法,参照下面的按用户ID取模。

4. 按照用户ID取模
    这里把按照用户ID取模单独拎出来,因为就使用而言,是使用场景最多的情况,很多时候都是用户相关数据量最大,需要分库分表,查询维度更多也是按照用户来查询,所以对用户取模,让同一个用户的数据落到一张表里面,再好不过了。

    案例:假设用户ID是整数型的。库数量要分4库,每个库表数量8表,一共32张表。

原理讲解:
一共要分4库,8表,共32张表,也就是1到32的用户ID要平均分配到每张表应该有一条数据,这样就有两种分法。
1) 1到8是第一个库,9到16第二个库,17到24第三个库,25到32是第四个库,每个库里面表的编号都是0到3,这个原则是一个库里面一个一个分,分完再下一个库一个一个分,保证不重复,不漏掉。
2)1,5,9这样每隔4个一个库,2开头隔4个一个库,这个原则是一个库分一个,在分下一个库,一圈走完,再在第一库没分到的表继续分,也保证了不重复,不漏掉原则。

库ID = userId % 库数量4
表ID = userId / 库数量4 % 表数量8

或者

库ID = userId / 表数量4 % 库数量4
表ID = userId % 表数量8


算法图示如下:



5. 数据路由表
如果分库分表的算法很复杂,可以通过路由表+程序算法,来存储和计算分库分表规则,不过一般不建议,分库分表搞得太复杂,不便于维护和查询问题

四、各个方案对比
分区算法
优点:线性扩容,平滑扩容,不需要数据迁移
缺点:存在热点数据,非时间维度查询多的情况,聚合复杂
建议:冷数据,用户维度查询少,且数据量大的情况用分区算法

取模算法
优点:同一个热点的数据可以做到一个表里面,查询方便
缺点:扩容不是很方便,需要数据迁移
建议:用户维度查询多,热点维度查询多的情况,建议使用


注:
    分库分表的核心是未来数据量的预估,根据预估和实际使用情况来确定分库分表方案,一般像订单类数据以用户维度取模分表最好,商品数据以商户取模最好,签到等活动流水数据时间分区最好。
    取模方案扩容的解决:一、可以提前按照预估方案创建库和表,前期放到一个DB,后期迁移,或者一次性弄好 二、可以按照预估的方案去确定分库和分表的后缀ID,但是前期只创建一部分库和表。例如:最终4库,每个库16个表。后缀应该是0000----0315共64个表的后缀,前期可以一个库,4个表,也就是所有数据都在这个四张表里面。
0000--0003-----》0000表
0100--0103-----》0000表
0200--0203-----》0000表
0300--0303-----》0000表

0004--0007-----》0004表
0104--0107-----》0004表
0204--0207-----》0004表
0304--0307-----》0004表

0008--0011-----》0008表
0108--0111-----》0008表
0208--0211-----》0008表
0308--0311-----》0008表

0012--0015-----》0012表
0112--0115-----》0012表
0212--0215-----》0012表
0312--0315-----》0012表

后续可以二分法,迁移数据,扩容。



欢迎大家关注我的公众号:


  • 大小: 156.4 KB
  • 大小: 9.2 KB
  • 大小: 26.7 KB
1
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics