MySQL 分库分表的方式总结

对于分库分表来说,具体有两种方式:垂直拆分和水平拆分
垂直拆分主要是业务的细化和独立,和业务联系比较密切。所以本文只讨论更通用的水平拆分。

为什么分库分表

  1. 降低单机 MySQL 的性能
  2. 降低单表或者单库的数据量,减少数据库的查询压力
  3. 突破单机的容量限制

分库分表的方式

  1. 范围区分(range):按月\按区\按其他的等特殊的属性维度进行分片
  2. 预定义范围:预估有多少数据的容量,对数据进行范围的分配,0-100->A 101-200->B
  3. 取模 Hash:对指定的字段进行取模运算,匹配对应的库和表。

分库分表带来的问题

  1. 数据的维护成本高
  2. 跨库的业务join
  3. 分布式事务的性能低下
  4. 自增 id 的生成问题
  5. 非分片字段查询的轮询的浪费
  6. 多节点排序问题

分库分表的中间件

对于分库分表的中间件有很多,Shardingsphere,Tddl,MyCat,cobar。从架构上分,主要分为两种:JDBC应用方式Proxy模式

JDBC应用模式是基于客户端的分片,有客户端根据Sql和规则,决定具体执行的 sql 的服务器。代表有Shardingsphere,Tddl

JDBC应用模式 优点:

  1. 性能好
  2. 支持跨数据库(mysql oralce mssq)

缺点:

  1. 不能跨语言
  2. 对开发不够友好,增加开发难度

Proxy模式 代理模式是基于 MySQL 做一层转发代理,有代理根据规则来分发具体的SQL 到服务器上。

优点:

  1. 跨语言
  2. 开发无感知

缺点:

  1. 性能比较差,增加了网络请求
  2. 不支持跨数据库
0

关于 MyCat 分库分表的一些理解

MyCat 是基于服务器代理模式的数据库分库的中间件,原理是对 SQL 进行转发,具体的架构图如下:

我们知道,数据的拆分必然会对事物的原子性带来影响,那如果保证在分库的同时,又能保证事务的原子性呢?

如何解决分布式事务

XA 协议

XA协议是一个开源的事务协议。

XA 协议在第二段协议 commit 事提交务后,如果出现了有的机器事务没有提交成功,有的机器已经提交成功,这时已经提交的数据,数据就无法再次回滚,这样就造成了数据不一致的问题。

三段提交协议

具体的协议如下:

相对于 XA 多了一个 Precommit的过程,在 Do-Commit的时候也增加了超时操作,避免了 XA 在 commit 无法收到 Ack 时候,出现了阻塞的现象。

业务的规则避免

这个是一个讨巧的方案,具体的做法是所有的业务表的修改和删除等操作,最终都能路由到一个 MySQL 的节点上面,这样就不存在分布式的事务问题。

如何解决唯一主键(自增)

这个本事是分布式的归一的一个思想。具体实施的思路有下面四种方式:

  1. 本地文件方式
  2. 数据库方式
  3. 时间戳
  4. 分布式zookeeper生成ID

如何查询非分片规则的数据

这个问题是一个很纠结的问题,因为没有什么特别好的办法。具体的思路应该有两种:

  1. 轮询各个节点查询,但是会带来性能的浪费。
  2. 未分片的字段与分片字段做一个映射,现根据非分片字段查询出分片字段。例如: 我们根据 Id 进行分片,如果我们想根据 userId 查询数据,有什么办法?首先要保证在业务数据的数量级,userid 一定是小于 id 的量级,所以我们可以直接存储 userid-> id1,id2….idn ,然后根据id 的集合查询出对应的数据。
+2