【MySQL】分库分表问题

时间:2021-10-29 01:25:00

将原本存储于单个数据库上的数据拆分到多个数据库,把原来存储在单张数据表的数据拆分到多张数据表中,实现数据切分,从而提升数据库操作性能。分库分表的实现可以分为两种方式:垂直切分和水平切分

水平:将数据分散到多张表,设计分区键

  • 分库:每个库结构一样,数据不一样,没有交集。库多了可以缓解IO和cpu压力。
  • 分表:每个表结构一样,数据不一样,没有交集。表数量减少可以提高sql执行效率、减轻cpu压力。

【分布式寻址】

1.按主键ID划分:可能后续大ID对应新数据,导致负载集中在某一部分。

2.ID求Hash值对数量取余,不利于扩展。

3.一致性Hash:「存储节点」和「数据」都映射到一个首尾相连的哈希环上,如果增加或者移除一个节点,仅影响该节点在哈希环上顺时针相邻的后继节点,其它数据也不会受到影响。

垂直:将字段拆分为多张表,需要一定的重构

  • 分库:每个库结构、数据都不一样。所有库的并集为全量数据。
  • 分表:每个表结构、数据不一样,至少有一列交集,用于关联数据,所有表的并集为全量数据。

分库分表引入的问题:

  • 分布式事务问题

对业务进行分库之后,同一个操作会分散到多个数据库中,涉及跨库执行 SQL 语句,也就出现了分布式事务问题。

比如数据库拆分后,订单和库存在两个库中,一个下单减库存的操作,就涉及跨库事务。关于分布式事务的处理,我们在专栏“分布式事务”的模块中也介绍过,可以使用分布式事务中间件,实现 TCC 等事务模型;也可以使用基于本地消息表的分布式事务实现。如果对这部分印象不深,你可以回顾下前面讲过的内容。

  • 跨库关联查询问题

分库分表后,跨库和跨表的查询操作实现起来会比较复杂,性能也无法保证。在实际开发中,针对这种需要跨库访问的业务场景,一般会使用额外的存储,比如维护一份文件索引。另一个方案是通过合理的数据库字段冗余,避免出现跨库查询。

  • 跨库跨表的合并和排序问题

分库分表以后,数据分散存储到不同的数据库和表中,如果查询指定数据列表,或者需要对数据列表进行排序时,就变得异常复杂,则需要在内存中进行处理,整体性能会比较差,一般来说,会限制这类型的操作。具体的实现,可以依赖开源的分库分表中间件来处理,下面就来介绍一下。

存储拆分后如何解决唯一主键问题

UUID:简单、性能好,没有顺序,没有业务含义,存在泄露mac地址的风险

数据库主键:实现简单,单调递增,具有一定的业务可读性,强依赖db、存在性能瓶颈,存在暴露业务信息的风险。

  • 同步长,不同初始值,扩展有问题。

  • 借助DB存储申请数量,可能没用完。

redis,mangodb,zk等中间件:增加了系统的复杂度和稳定性

雪花算法