什么是分库分表
简单来说,就是指通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面,以达到分散单台设备负载的效果。
-
分库分表解决的问题
分库分表的目的是为了解决由于数据量过大而导致数据库性能降低的问题,将原来单体服务的数据库进行拆分.将数据大表拆分成若干数据表组成,使得单一数据库、单一数据表的数据量变小,从而达到提升数据库性能的目的。
-
什么情况下需要分库分表
-
单机存储容量遇到瓶颈.
-
连接数,处理能力达到上限.
-
注意:
分库分表之前,要根据项目的实际情况 确定我们的数据量是不是够大,并发量是不是够大,来决定是否分库分表.
数据量不够就不要分表,单表数据量超过1000万或100G的时候, 速度就会变慢(官方测试),
分库分表包括: 垂直分库、垂直分表、水平分库、水平分表 四种方式。
垂直分库
-
数据库中不同的表对应着不同的业务,垂直切分是指按照业务的不同将表进行分类,分布到不同的数据库上面
-
将数据库部署在不同服务器上,从而达到多个服务器共同分摊压力的效果
-
垂直分表
表中字段太多且包含大字段的时候,在查询时对数据库的IO、内存会受到影响,同时更新数据时,产生的binlog文件会很大,MySQL在主从同步时也会有延迟的风险
-
将一个表按照字段分成多表,每个表存储其中一部分字段。
-
对职位表进行垂直拆分, 将职位基本信息放在一张表, 将职位描述信息存放在另一张表
-
垂直拆分带来的一些提升
-
解决业务层面的耦合,业务清晰
-
能对不同业务的数据进行分级管理、维护、监控、扩展等
-
高并发场景下,垂直分库一定程度的提高访问性能
-
-
垂直拆分没有彻底解决单表数据量过大的问题
水平分库
-
将单张表的数据切分到多个服务器上去,每个服务器具有相应的库与表,只是表中数据集合不同。 水平分库分表能够有效的缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源等的瓶颈.
-
简单讲就是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面, 例如将订单表 按照id是奇数还是偶数, 分别存储在不同的库中。
水平分表
-
针对数据量巨大的单张表(比如订单表),按照规则把一张表的数据切分到多张表里面去。 但是这些表还是在同一个库中,所以库级别的数据库操作还是有IO瓶颈。
-
总结
-
垂直分表: 将一个表按照字段分成多表,每个表存储其中一部分字段。
-
垂直分库: 根据表的业务不同,分别存放在不同的库中,这些库分别部署在不同的服务器.
-
水平分库: 把一张表的数据按照一定规则,分配到不同的数据库,每一个库只有这张表的部分数据.
-
水平分表: 把一张表的数据按照一定规则,分配到同一个数据库的多张表中,每个表只有这个表的部分数据.
-
水平分库分表策略
分库分表策略一般有几种,使用与不同的场景:
-
range范围
-
hash取模
-
range+hash取模混合
1 range范围
range,即范围策略划分表。比如我们可以将表的主键,按照从0~1000万
的划分为一个表,1000~2000万
划分到另外一个表。如下图:
当然,有时候我们也可以按时间范围来划分,如不同年月的订单放到不同的表,它也是一种range的划分策略。
这种方案的优点:
-
这种方案有利于扩容,不需要数据迁移。假设数据量增加到5千万,我们只需要水平增加一张表就好啦,之前
0~4000万
的数据,不需要迁移。
缺点:
-
这种方案会有热点问题,因为订单id是一直在增大的,也就是说最近一段时间都是汇聚在一张表里面的。比如最近一个月的订单都在
1000万~2000
万之间,平时用户一般都查最近一个月的订单比较多,请求都打到order_1
表啦,这就导致表的数据热点问题。
2 hash取模
hash取模策略:指定的路由key(一般是user_id、订单id作为key)对分表总数进行取模,把数据分散到各个表中。
比如原始订单表信息,我们把它分成4张分表:
-
比如id=1,对4取模,就会得到1,就把它放到第1张表,即
t_order_0
; -
id=3,对4取模,就会得到3,就把它放到第3张表,即
t_order_2
;
这种方案的优点:
-
hash取模的方式,不会存在明显的热点问题。
缺点:
-
如果一开始按照hash取模分成4个表了,未来某个时候,表数据量又到瓶颈了,需要扩容,这就比较棘手了。比如你从4张表,又扩容成
8
张表,那之前id=5
的数据是在(5%4=1
,即第一张表),现在应该放到(5%8=5
,即第5
张表),也就是说历史数据要做迁移了。
3 range+hash取模混合
既然range存在热点数据问题,hash取模扩容迁移数据比较困难,我们可以综合两种方案一起嘛,取之之长,弃之之短。
比较简单的做法就是,在拆分库的时候,我们可以先用range范围方案,比如订单id在04000万的区间,划分为订单库1,id在4000万8000万的数据,划分到订单库2,将来要扩容时,id在8000万~1.2亿的数据,划分到订单库3。然后订单库内,再用hash取模的策略,把不同订单划分到不同的表。
分库分表会导致哪些问题
分库分表之后,也会存在一些问题:
-
事务问题
-
跨库关联
-
排序问题
-
分页问题
-
分布式ID
1 事务问题
分库分表后,假设两个表在不同的数据库,那么本地事务已经无效啦,需要使用分布式事务了。
2 跨库关联
跨节点Join的问题:解决这一问题可以分两次查询实现
3 排序问题
跨节点的count,order by,group by以及聚合函数等问题:可以分别在各个节点上得到结果后在应用程序端进行合并。
4 分页问题
-
方案1:在个节点查到对应结果后,在代码端汇聚再分页。
-
方案2:把分页交给前端,前端传来pageSize和pageNo,在各个数据库节点都执行分页,然后汇聚总数量前端。这样缺点就是会造成空查,如果分页需要排序,也不好搞。
5 分布式ID
据库被切分后,不能再依赖数据库自身的主键生成机制啦,最简单可以考虑UUID,或者使用雪花算法生成分布式ID。
分库分表中间件
目前流行的分库分表中间件比较多:
-
cobar
-
Mycat
-
Sharding-JDBC
-
Atlas
-
TDDL(淘宝)
-
vitess
知识来源:马士兵教育
12张图把分库分表讲的明明白白!