Listening to the Words

MySQL分库分表操作之Mycat中间件

MySQL分库分表操作之Mycat中间件

《MySQL分库分表操作之Mycat中间件》


几乎所有程序员都知道一个事实,如果你的数据库数据量非常大的时候,比如超过了1000万行数据时,在并发下mysql的响应是很慢的。

这时谈到优化每个人都会回答:优化SQ语句和分库分表,读写分离。

完全正确,这样回答没有什么问题。 但是先冷静下…… 如何做呢?

who can do it?

本文是假定所有的索引语句优化都做过了,确保没有类似于慢语句的sql,接下来只能从分库分表这个方向进行优化。

都说半夜想来千条路,早起还需磨豆腐,作为一个程序员,不管经验深浅,如果现在摆在你面前的是读写分离和分库分表等需求,你的第一反应是什么?想必是两眼一抹黑,这东西看起来即繁琐又很难,根本找不到切入点。

没错,早期的应用程序面对的流量都不大,数据量也不会很多,因此很多用不到这类优化方式,稍微大点的项目也就是程序员简单的实现个分库分表即可了。

然后,现在的年代,很显然做什么都要为大流量高并发做准备(事实上大多数项目仍然没有这个瓶颈)。

试想下:这个优化有多少个方式?

有三种:

  1. 程序端自己分库分表
  2. 中间代理
  3. mysql官方提供解决方案

第一种看起来就是噩梦,几乎会累死人。第三种看起来很好,只是mysql官方会累死。于是合理的方案只有第二种 :中间代理

Middleware Proxy

中间件是一个最近几年很火的概念,它带来的最大好处就是解耦,它就是在牛郎和织女间的喜鹊桥,双方都感知不到它的存在。

于是真正的主角出场了:Mycat

Mycat

《MySQL分库分表操作之Mycat中间件》

Mycat的核心原理是 拦截;拦截用户发出的SQL语句,经过一些列的分析,将处理过的语句分配给不同的真实数据库,最后从数据库获取结果,处理合并后返回给用户。

这是所有中间件应用的核心

  • 路由分析
  • 读写分离分析
  • 缓存分析
  • 分片分析

Mycat实际运行时会存在一个逻辑数据库区映射物理数据库

Mysql读写分离

mysql的读写分离基本分为两种: 单主单从 和多主多从:

《MySQL分库分表操作之Mycat中间件》

主从复制基本的原理是:从机从主机的binlog日志获取到数据,然后I/O复制回到自己的Relay日志,接着在同步到自己的数据库里去。这个起始点不是全量的也不是增量的,而是有一个position的概念,从机在哪里(通常是个position位置数值)加入的就从哪里开始同步。

因此这样的过程势必有一个问题:延迟问题。

多主多从:有多个主机和多个从机,主机间互相备份互相配置。一台挂掉另一台成为主机。

在mycat的读写分离配置中有个属性balance配置,通常配置为1 和 3 即 单主单从 和多主多从

数据库垂直拆分原则(分库)

mycat提供了垂直拆分配置,垂直拆分数据库是一件相对简单的工作,基本遵循一个原则:根据业务来做拆分,粒度上以能不能使用join做参考(不同的数据库间不能使用join)

数据库水平拆分原则(分表,分片)

水平拆分利用的分治原则,将数据分开然后分配到不同的存储空间。

数据库的水平拆分实际上很麻烦,以订单表为例拆分数据表:

mycat提供了完善的分片分表配置和功能,以订单表为了例子:选择哪个字段作为分片的依据呢?主键id吗?还是时间?

这两个都不好,因为主键id不能讲数据平衡分配到多个数据库里,就会导致有的数据库压力巨大,有的数据库压力很小,
时间字段也有类似的情况,用户通常不会查询自己很久以前的订单,一把都是最近几天的订单状态。

最好的是 用户id:按照用户id来划分,每个用户的数据放入一个物理机器里,这样就能保证数据的基本平衡。

一下是四种基本的分片依据原则:

  • hash 取模 (根据拆分属性的数据与数据库机器取模)
  • 分片枚举(省份 编码等)
  • 范围约定(数字范围)
  • 日期分片

这些方法在mycat中都有算法实现和配置项

分片join难题

mycat的分片时会遇到一种情况,表 A join B,如果A做了分片,数据存储在不同的数据库里,B没做,而且B 还是A的附属表(订单和订单详情表),这种情况下使用Join语句关联查询时,会报错,因为可能有一台机器中没有记录甚至没有表(未有分表分片)。

因此mycat提供一个父子表的属性,允许你将一个表设置为主表的子表,他们之间使用主键和外键关联,这样查询操作时两张表都有了分片

全局表(字典表)

全局表具有以下特点:

  • 变化小
  • 数量小
  • 到处用

mycat也提供了全局表的功能,配置属性为global,这个表就会以数据冗余的形式,存在在所有数据库里。

全局序列

全局序列是为了解决多台数据库数据自增时候可能产生的主键冲突难题,通常有三种办法:

  • 本地文件序列
  • 数据库方式
  • 时间戳方式

本地文件序列最大的缺点是不稳定,一旦一台主机挂掉了,其他主机就没法拿到它的本地文件,服务变得不可用

时间戳方式也能解决这个问题,但是缺点是uuid过长利用效率太低

最后推荐使用的是数据库方式:mycat在一张数据写入生成序列算法,每次取出一部分自增序列放在内存里,使用完后再去申请。一旦主机挂掉当前一批的自增序列就无法使用。自动切换到下一批序列。

结语

mycat中间件很好地解决了大多数程序员面对大数据时的痛苦,它采用中间件的形式无痛的解耦了客户端和服务端。

点赞