为什么分库分表

192 阅读5分钟

1 什么是分库分表?

其实就是字面意思,很好理解:

  • 分库:从单个数据库拆分成多个数据库的过程,将数据散落在多个数据库中。
  • 分表:从单张表拆分成多张表的过程,将数据散落在多张表内。

2 为什么要分库分表?

关键字:提升性能、增加可用性。

2.1 从性能上看

随着单库中的数据量越来越大、数据库的查询QPS越来越高,相应的,对数据库的读写所需要的时间也越来越多。数据库的读写性能可能会成为业务发展的瓶颈。对应的,就需要做数据库性能方面的优化。本文中我们只讨论数据库层面的优化,不讨论缓存等应用层优化的手段。

如果数据库的查询QPS过高,就需要考虑拆库,通过分库来分担单个数据库的连接压力。比如,如果查询QPS为3500,假设单库可以支撑1000个连接数的话,那么就可以考虑拆分成4个库,来分散查询连接压力。

如果单表数据量过大,当数据量超过一定量级后,无论是对于数据查询还是数据更新,在经过索引优化等纯数据库层面的传统优化手段之后,还是可能存在性能问题。这是量变产生了质变,这时候就需要去换个思路来解决问题,比如:从数据生产源头、数据处理源头来解决问题,既然数据量很大,那我们就来个分而治之,化整为零。这就产生了分表,把数据按照一定的规则拆分成多张表,来解决单表环境下无法解决的存取性能问题。

2.2 从可用性上看

单个数据库如果发生意外,很可能会丢失所有数据。尤其是云时代,很多数据库都跑在虚拟机上,如果虚拟机/宿主机发生意外,则可能造成无法挽回的损失。因此,除了传统的 Master-Slave、Master-Master 等部署层面解决可靠性问题外,我们也可以考虑从数据拆分层面解决此问题。

此处我们以数据库宕机为例:

  • 单库部署情况下,如果数据库宕机,那么故障影响就是100%,而且恢复可能耗时很长。
  • 如果我们拆分成2个库,分别部署在不同的机器上,此时其中1个库宕机,那么故障影响就是50%,还有50%的数据可以继续服务。
  • 如果我们拆分成4个库,分别部署在不同的机器上,此时其中1个库宕机,那么故障影响就是25%,还有75%的数据可以继续服务,恢复耗时也会很短。

当然,我们也不能无限制的拆库,这也是牺牲存储资源来提升性能、可用性的方式,毕竟资源总是有限的。

3 方案:

切分方案解决的问题
只分库不分表数据库读/写QPS过高,数据库连接数不足
只分表不分库单表数据量过大,存储性能遇到瓶颈
既分库又分表连接数不足+数据量过大引起的存储性能瓶颈

3.1 如何对数据进行切分?

根据行业惯例,通常按照水平切分、垂直切分两种方式进行切分,当然,有些复杂业务场景也可能选择两者结合的方式。

(1)水平切分

这是一种横向按业务维度切分的方式,比如常见的按会员维度切分,根据一定的规则把不同的会员相关的数据散落在不同的库表中。由于我们的业务场景决定都是从会员视角进行数据读写,所以,我们就选择按照水平方式进行数据库切分。

(2)垂直切分

垂直切分可以简单理解为,把一张表的不同字段拆分到不同的表中。

比如:假设有个小型电商业务,把一个订单相关的商品信息、买卖家信息、支付信息都放在一张大表里。可以考虑通过垂直切分的方式,把商品信息、买家信息、卖家信息、支付信息都单独拆分成独立的表,并通过订单号跟订单基本信息关联起来。

也有一种情况,如果一张表有10个字段,其中只有3个字段需要频繁修改,那么就可以考虑把这3个字段拆分到子表。避免在修改这3个数据时,影响到其余7个字段的查询行锁定。

4.遇到什么问题

  1. 全局pk(主键和唯一索引)的冲突检测不准确,全局的自增主键支持不够好。
  2. 分片键的选择。如没有选择好,可能会影响SQL执行效率。
  3. 分布式事物,中间件产品对分布式事物的支持力度。
  4. 对于开发来说,需要进行业务的拆分
  5. 对于开发来说,部分SQL不兼容则需要代码重构,工作量的评估
  6. 对于开发来说,跨库join,跨库查询

如何解决

  1. 使用全局分号器。或者使用全局唯一id,(应用生成顺序唯一int类型做为全局主键)。
  2. 应用层来判断唯一索引。
  3. 配合应用选择合适的分片键,并加上索引。
  4. 配合应用,配合开发,对不兼容SQL的进行整改。

业界分库分表方案:参考:blog.csdn.net/qinzexins/a…