一、拆分方式
数据库拆分的方式一般就是水平拆分,和垂直拆分
1、垂直拆分
垂直拆分比较简单,数据量大了之后,从业务角度触发进行拆分多个库,订单库,商品库,用户库,做到高内聚。如下图,独立的拆分出订单库和用户库。
2、水平拆分
水平拆分的概念,是同一个业务数据量大之后,进行水平拆分
二、分库分表方案
hash取模和range范围方案;
1、hash取模:需要知道我们有 mod(key) = key/n ,我们需要知道n等于几;
-
优点:
订单数据如果key分布均匀的话数据就可以均匀的放到那4张表中,这样此订单进行操作时,就不会有热点问题。
-
缺点:
将来的数据迁移和扩容,会很难。
如:业务发展很好,订单量很大,超出了4000万的量,那我们就需要增加分表数。如果我们增加4个表
-
一旦我们增加了分表的总数,取模的基数就会变成8,以前 key = 12 的订单按照此方案就会到4表中查询,但之前的此订单时在0表的,这样就导致了数据查不到。就是因为取模的基数产生了变化。
2、range范围方案
按key的范围存到到不同的表里,自增主键,时间范围,城市地域等都可以;
优点:
扩容方便不需要数据迁移,扩容之后新数据落到新的表里,而老数据不用改变
缺点:
冷热数据,ID自增,时间推移之后,会造成新的表数据不断积累,读写都在这个表里,表数据过热等;
3、总结:
hash取模方案:没有热点问题,但扩容迁移数据痛苦
range方案:不需要迁移数据,但有热点问题。
那么如何才能做到又不需要数据迁移,又能做到避免数据的热点问题呢?
三、方案思路
hash方案是解决的是数据均匀的问题,
range方案解决的是数据迁移问题,
随着数据的不断增长,我们需要保证数据不要迁移,然后解决所有数据的热点问题;
首先使用range方案让数据落到一个范围里;这样就不会迁移;
首先要明白为什么要数据扩容?
1、空间不足
2,性能不足
那我们每次的扩容事先设计好这次扩容的大小范围就可以了,
所以我们只要保证这次的范围内的数据均匀是不是就ok了,在这次大的范围内使用hash策略。
key数据步骤
1、key =0~4000万的请求根据range方案 落到group01组中
2、group01组有3个DB,那一个id如何路由到哪个DB?
3、根据hash取模定位DB,那模数为多少?模数要为所有此group组DB中的表数,上图总表数为10。为什么要去表的总数?而不是DB总数3呢?
4、如key =12,key %10=2;那值为2,落到哪个DB库呢?这是设计是前期设定好的,那怎么设定的呢?
5、一旦设计定位哪个DB后,就需要确定落到DB中的哪张表呢?
按照上面的流程,我们就可以根据此规则,定位一个key,我们看看有没有避免热点问题。
我们看一下,key 在【0,1000万】范围内的,根据上面的流程设计,1000万以内的 key 都均匀的分配到 DB_0,DB_1,DB_2三个数据库中的Table_0表中,为什么可以均匀,因为我们用了hash的方案,对10进行取模。10 为什么是10呢,因为我们有10张表,按表的总数取模,这样能保证数据的分布;如果按照数据库的个数取模就不能保证按数据库性能或者存储来分布式数据
不同的服务器性能和存储能力不同
六、如何扩容
就是按原来的规则定义新的group组,按照key 和数据库和DB的映射关系来存储,可以在旧的数据库中新增表,也可以在新增数据库新增表,只要按原来的规则配置好key和group的映射关系就好了;
七、映射表设计
group,表的字段设计
groupid,
group_name,
start_id,
end_id
DB表的设计,
db_id,
db_name
group_id,
hash_value;
table表设计:
table_id,
table_name,
db_id,
start_id,
end_id,
如果新增分组的的扩容映射,需要重新加载关系,需要发布与订阅关系,可以使用分布式配置中心去发布新的配置信息,所有分布式节点订阅更新数据同时生效;同时要注意 key 必须是自增的,或者自增趋势