先来一张熟悉的主从架构:
如果现在有海量的数据需要存储,这个架构就不能解决了,因为现在的主库和从库存储的·数据都是一样的,主要解决的时访问的压力,是解决不了海量的数据存储的。现在就需要分库分表了。
分库分表的时机
前提:项目业务数据逐渐增多,或业务发展比较迅速,数据库可能承受不住,就需要分库分表。
一般在企业中,单表数据量达到1000w或20G以后,可能就是分库分表的信号了,因为达到了这个量级,优化以及解决不了性能问题了。(主从读写分离、查询索引...)
当用户量上来以后我们会遭遇两个瓶颈:
- IO瓶颈(磁盘IO和网络IO)
- CPU瓶颈(聚合查询,连接数不多):如果一个表的数据量太多,那么我们在聚合查询的时候会耗费CPU
分库分表的策略
分库的意思是将一个数据库的数据分到多个数据库存储,而分表的意思是将一张表的内容存储在多个表上。
垂直拆分
垂直分库
以表为依据,根据不同的业务,将不同的表拆分到不同的库中。
如图,左侧是一个电商业务的数据库,一共有六张表,首先前面两种都是和用户有关系,中间两种都是跟订单有关系,最后两张是商品表,那我们就可以根据不同业务,分为用户,订单,商品三个数据库。在我们开发微服务的时候,每个微服务都会对于一个数据库。
特点:
- 按照业务对数据分级管理,扩展
- 在高并发下,提高磁盘IO和连接数
垂直分表
以字段为依据,根据字段属性拆分到不同表中。
拆分规则:1.把不常用的字段单独放在一张表
2.把text等大字段拆分出来放在附表中
如图,我们给商品表分成两个表存储,分别存储不同的数据,上面的是基本信息,下面的是商品的描述信息,这两个是一对一的关系。(实际开发中,也有可能是一个数据库下拆分成两张表)
垂直拆分特点:
- 冷热数据分离
- 减少IO过度争抢,两表互不影响。
水平拆分
水平分库
将一个库的数据拆分到多个库中
如图,数据库中有两张表,订单表和订单详情表。随着订单数量越来越多,一个库装不下,就需要拆分到各个库中。注意,这几个库中每个库存储的数据是不一样的,所有的库加起来才是这个订单业务的所有的数据。那么此时我们在查询的时候该如何找到对应的数据呢?
我们的应用在查询的时候会有一些路由的规则,常用规则如下:
- 根据id节点取模
- 按id也就是范围路由,节点1(1~100w)节点2(100w~200w)
水平分库解决了单库大数据量,高并发的性能瓶颈问题,提高了系统的稳定性和可用性
水平分表
将一个表的数据拆分到多个表中(可以在同一个库中)
如图,图中的订单表就拆到了不同的数据库中,每个库都是存储的订单表
这种水平分表的优点就是:优化单一表数据量过大而产生的性能问题;避免IO争抢并减少锁表几率。
分库分表的注意事项
当我们一个应用连接多个数据库,我们还要按照取模的方式找到各个数据库,如果当前读数据库由做了集群那我们操作起来就更加复杂了。
我们在分库分表时常见的问题有这几种:
分布式事务问题:我们现在有多个库多个表,如果我们的业务比较复杂,需要在不同的库中同时操作多个表,并且在不同的库中,每个库都要管理自己的事务,假如自己的事务提交失败了,其他事务要正常提交,此时就有可能产生事务不一致的问题。
跨节点关联查询:如果两个库A和B分表存储不同的表,A和B中间的表还要进行关联。
跨节点分页,排序
主键避重
为了解决这些问题我们就需要使用一些数据库的中间件,比如MyCat,shading-sphere等等