undefined

二、高性能数据库集群:分库分表

读写分离分散了数据库的读写操作的压力,但没有分散存储压力,体现在几个方面

  • 数据量大,读写性能下降,即使有索引,索引也会很大
  • 数据文件很大,数据库备份和恢复需要耗费很长时间
  • 数据文件越大,极端情况下丢失数据的风险越高(例如机房火灾导致的主备机都故障)

1. 业务分库

按照业务模块将数据分散到不同的数据库服务器。例如电商网站,将用户数据、商品数据、订单数据分开到三台不同的数据库服务器
引入问题:

  • 无法使用 join 操作,原本在同一个数据库中的表分散到不同数据库中
  • 事务问题,业务分库后,表分散到不同数据库,无法通过事务统一修改,虽然有分布式事务的解决方案(MySQL的XA),但性能太低
  • 成本问题,原来需要 1 台数据库现在需要 3 台,考虑备份,需要 6 台

2. 业务分表

同一业务的单表数据会达到单台数据库服务器的处理瓶颈。比如微信的几亿用户数据,如果全部存储到一张表中,无法满足性能要求,此时需要对单表数据进行拆分。单表数据拆分有两种方式:垂直分表水平分表

  • 垂直分表,适合将表中某些不常用且占用了大量空间的列拆分出去。缺点:导致表操作的次数要增加,原本一次查询可能需要多次查询。

  • 水平分表,比如单表行数超过 5000万就分表,这不是标准,有个比较复杂的表,可能超过 1000万就要分表。
    缺点:

    1. 某条数据具体属于那个切分后的表,需要增加路由算法进行计算,这个算法有一定复杂度

      路由算法:
      (1). 范围路由:以用户ID为例,1-100w 存储在数据库1的表中,100w-200w存储到数据库2的表中。优点:可以随着数据的增加平滑的扩充新的表。缺点:分布不均匀,可能表 1 存储 1000条数据,表 2 存储 100w 条数据
      (2). hash 路由:选取某个列(或者几个列的组合)的值进行 hash 运算,将数据分散到不同数据库表中。难点:初始表数量的选取,表数据太多维护比较麻烦,表数量太少会导致单表性能存在问题。且增加子表数量非常麻烦,所有数据需要重分布。优点:表分布比较均匀。缺点:扩充新表比较麻烦,所有数据都要重分布

      (3). 配置路由:用一张独立的表来记录路由信息,设计简单,扩充表的时候,只需要迁移指定数据,然后修改路由表即可。缺点:多查询一次影响性能,且路由表如果太大,性能瓶颈。

    2. join 操作,水平分表后,数据分散在多个表,如果需要与其他表进行 join 查询,需要在业务代码或者数据库中间件 进行多次 join 查询,然后合并

    3. count() 操作,可能某些业务逻辑还是会将这些表当作一个表来处理,比如获取记录总数 count() 操作就需要多次,然后合并返回,性能低。不过可以记录业务数据,即新建一张表然后记录