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

一、背景: 
    系统刚开始的时候,数据库都是单库单表结构。随着业务量的增加进行第一次数据库升级,根据业务垂直拆分数据库,这样多变成多个业务数据库,每个数据库里面还是单表结构。接下来,继续随着业务量的继续增加,单表已经很难承受数据量,就要进行分表,这个时候就是,多个业务库,每个业务库下对需要分表的表进行分表。再接下来,随着应用的增加,数据库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表 

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

 

原文地址:http://825635381.iteye.com/blog/2368838

posted @ 2018-06-10 23:03  lwli  阅读(679)  评论(0编辑  收藏  举报