Mycat相关介绍和不适应场景列举

工作需要使用Mycat作为数据库连接,所以去网上找了点相关资料。

Mycat介绍

Mycat是什么?从定义和分类来看,它是一个开源的分布式数据库系统,是一个实现了MySQL协议的的Server,前端用户可以把

它看作是一个数据库代理,用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生(Native)协议与多个MySQL服务
器通信,也可以用JDBC协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为N个小表,存储

在后端MySQL服务器里或者其他数据库里。

Mycat发展到目前的版本,已经不是一个单纯的MySQL代理了,它的后端可以支持MySQL、SQL Server、Oracle、DB2、
PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储,未来还会支持更多类型的存储。而在最终用户看
来,无论是那种存储方式,在Mycat里,都是一个传统的数据库表,支持标准的SQL语句进行数据的操作,这样一来,对前端业
务系统来说,可以大幅降低开发难度,提升开发速度,在测试阶段,可以将一个表定义为任何一种Mycat支持的存储方式,比如
MySQL的MyASIM表、内存表、或者MongoDB、LevelDB以及号称是世界上最快的内存数据库MemSQL上。试想一下,用户表
存放在MemSQL上,大量读频率远超过写频率的数据如订单的快照数据存放于InnoDB中,一些日志数据存放于MongoDB中,
而且还能把Oracle的表跟MySQL的表做关联查询,你是否有一种不能呼吸的感觉?而未来,还能通过Mycat自动将一些计算分析
后的数据灌入到Hadoop中,并能用Mycat+Storm/Spark Stream引擎做大规模数据分析,看到这里,你大概明白了,Mycat是
什么?Mycat就是BigSQL,Big Data On SQL Database。
对于DBA来说,可以这么理解Mycat:
Mycat就是MySQL Server,而Mycat后面连接的MySQL Server,就好象是MySQL的存储引擎,如InnoDB,MyISAM等,因
此,Mycat本身并不存储数据,数据是在后端的MySQL上存储的,因此数据可靠性以及事务等都是MySQL保证的,简单的
说,Mycat就是MySQL最佳伴侣,它在一定程度上让MySQL拥有了能跟Oracle PK的能力。
对于软件工程师来说,可以这么理解Mycat:
Mycat就是一个近似等于MySQL的数据库服务器,你可以用连接MySQL的方式去连接Mycat(除了端口不同,默认的Mycat端
口是8066而非MySQL的3306,因此需要在连接字符串上增加端口信息),大多数情况下,可以用你熟悉的对象映射框架使用
Mycat,但建议对于分片表,尽量使用基础的SQL语句,因为这样能达到最佳性能,特别是几千万甚至几百亿条记录的情况下。
对于架构师来说,可以这么理解Mycat:
Mycat是一个强大的数据库中间件,不仅仅可以用作读写分离、以及分表分库、容灾备份,而且可以用于多租户应用开发、云平
台基础设施、让你的架构具备很强的适应性和灵活性,借助于即将发布的Mycat智能优化模块,系统的数据访问瓶颈和热点一目
了然,根据这些统计分析数据,你可以自动或手工调整后端存储,将不同的表映射到不同存储引擎上,而整个应用的代码一行也

不用改变。

Mycat原理

Mycat的原理并不复杂,复杂的是代码,如果代码也不复杂,那么早就成为一个传说了。
Mycat的原理中最重要的一个动词是“拦截”,它拦截了用户发送过来的SQL语句,首先对SQL语句做了一些特定的分析:如分
片分析、路由分析、读写分离分析、缓存分析等,然后将此SQL发往后端的真实数据库,并将返回的结果做适当的处理,最终再
返回给用户。

上述图片里,Orders表被分为三个分片datanode(简称dn),这三个分片是分布在两台MySQL Server上(DataHost),即
datanode=database@datahost方式,因此你可以用一台到N台服务器来分片,分片规则为(sharding rule)典型的字符串枚举
分片规则,一个规则的定义是分片字段(sharding column)+分片函数(rule function),这里的分片字段为prov而分片函数为字
符串枚举方式。
当Mycat收到一个SQL时,会先解析这个SQL,查找涉及到的表,然后看此表的定义,如果有分片规则,则获取到SQL里分片字
段的值,并匹配分片函数,得到该SQL对应的分片列表,然后将SQL发往这些分片去执行,最后收集和处理所有分片返回的结果
数据,并输出到客户端。以select * from Orders where prov=?语句为例,查到prov=wuhan,按照分片函数,wuhan返回
dn1,于是SQL就发给了MySQL1,去取DB1上的查询结果,并返回给用户。
如果上述SQL改为select * from Orders where prov in (‘wuhan’,‘beijing’),那么,SQL就会发给MySQL1与MySQL2去
执行,然后结果集合并后输出给用户。但通常业务中我们的SQL会有Order By 以及Limit翻页语法,此时就涉及到结果集在
Mycat端的二次处理,这部分的代码也比较复杂,而最复杂的则属两个表的Jion问题,为此,Mycat提出了创新性的ER分片、全
局表、HBT(Human Brain Tech)人工智能的Catlet、以及结合Storm/Spark引擎等十八般武艺的解决办法,从而成为目前业界
最强大的方案,这就是开源的力量!

 

应用场景

Mycat发展到现在,适用的场景已经很丰富,而且不断有新用户给出新的创新性的方案,以下是几个典型的应用场景:
单纯的读写分离,此时配置最为简单,支持读写分离,主从切换
分表分库,对于超过1000万的表进行分片,最大支持1000亿的单表分片
多租户应用,每个应用一个库,但应用程序只连接Mycat,从而不改造程序本身,实现多租户化
报表系统,借助于Mycat的分表能力,处理大规模报表的统计
替代Hbase,分析大数据
作为海量数据实时查询的一种简单有效方案,比如100亿条频繁查询的记录需要在3秒内查询出来结果,除了基于主键的查
询,还可能存在范围查询或其他属性查询,此时Mycat可能是最简单有效的选择
Mycat长期路线图
强化分布式数据库中间件的方面的功能,使之具备丰富的插件、强大的数据库智能优化功能、全面的系统监控能力、以及方
便的数据运维工具,实现在线数据扩容、迁移等高级功能
进一步挺进大数据计算领域,深度结合Spark Stream和Storm等分布式实时流引擎,能够完成快速的巨表关联、排序、分组
聚合等 OLAP方向的能力,并集成一些热门常用的实时分析算法,让工程师以及DBA们更容易用Mycat实现一些高级数据分
析处理功能。

Mycat不适应场景列举

1.非分片字段查询

Mycat中的路由结果是通过分片字段分片方法来确定的。例如下图中的一个Mycat分库方案:

·        根据 tt_waybill 表的 id 字段来进行分片

·        分片方法为 id 值取 3 的模,根据模值确定在DB1DB2DB3中的某个分片

如果查询条件中有 id 字段的情况还好,查询将会落到某个具体的分片。例如:

mysql>select * fromtt_waybill where id =12330;

此时Mycat会计算路由结果

12330 % 3 = 0 –> DB1

并将该请求路由到DB1上去执行。 


如果查询条件中没有 分片字段 条件,例如:

mysql>select * fromtt_waybill where waybill_no =88661;

此时Mycat无法计算路由,便发送到所有节点上执行:

DB1 –> select * fromtt_waybill where waybill_no =88661; 
DB2 –> select * from tt_waybill where waybill_no =88661; 
DB3 –> select * from tt_waybill where waybill_no =88661;

如果该分片字段选择度高,也是业务常用的查询维度,一般只有一个或极少数个DB节点命中(返回结果集)。示例中只有3个DB节点,而实际应用中的DB节点数远超过这个,假如有50个,那么前端的一个查询,落到MySQL数据库上则变成50个查询,会极大消耗Mycat和MySQL数据库资源。

如果设计使用Mycat时有非分片字段查询,请考虑放弃!

2.分页排序

先看一下Mycat是如何处理分页操作的,假如有如下Mycat分库方案: 
一张表有30份数据分布在3个分片DB上,具体数据分布如下

DB1[0,1,2,3,4,10,11,12,13,14] 
DB2[5,6,7,8,9,16,17,18,19] 
DB3[20,21,22,23,24,25,26,27,28,29]

(这个示例的场景中没有查询条件,所以都是全分片查询,也就没有假定该表的分片字段和分片方法)

当应用执行如下分页查询时

mysql>select * fromtable limit 2;

Mycat将该SQL请求分发到各个DB节点去执行,并接收各个DB节点的返回结果

DB1: [0,1] 
DB2: [5,6] 
DB3: [20,21]

但Mycat向应用返回的结果集取决于哪个DB节点最先返回结果给Mycat。如果Mycat最先收到DB1节点的结果集,那么Mycat返回给应用端的结果集为 [0,1],如果Mycat最先收到DB2节点的结果集,那么返回给应用端的结果集为 [5,6]。也就是说,相同情况下,同一个SQL,在Mycat上执行时会有不同的返回结果。

在Mycat中执行分页操作时必须显示加上排序条件才能保证结果的正确性,下面看一下Mycat对排序分页的处理逻辑。 
假如在前面的分页查询中加上了排序条件(假如表数据的列名为id

mysql>select * fromtable orderby id limit 2;

Mycat的处理逻辑如下图:

在有排序呢条件的情况下,Mycat接收到各个DB节点的返回结果后,对其进行最小堆运算,计算出所有结果集中最小的两条记录 [0,1] 返回给应用。

但是,当排序分页中有 偏移量 (offset)时,处理逻辑又有不同。假如应用的查询SQL如下:

mysql>select * fromtable order by id limit 5,2;

如果按照上述排序分页逻辑来处理,那么处理结果如下图:

Mycat将各个DB节点返回的数据 [10,11],[16,17], [20,21] 经过最小堆计算后返回给应用的结果集是 [10,11]。可是,对于应用而言,该表的所有数据明明是 0-29 这30个数据的集合,limit 5,2 操作返回的结果集应该是 [5,6],如果返回 [10,11] 则是错误的处理逻辑。

所以Mycat在处理 有偏移量的排序分页 时是另外一套逻辑——改写SQL 。如下图:

Mycat在下发有 limit m,n 的SQL语句时会对其进行改写,改写成 limit 0, m+n 来保证查询结果的逻辑正确性。所以,Mycat发送到后端DB上的SQL语句是

mysql>select * fromtable order by id limit 0,7;

各个DB返回给Mycat的结果集是

DB1: [0,1,2,3,4,10,11] 
DB2: [5,6,7,8,9,16,17] 
DB3: [20,21,22,23,24,25,26]

经过最小堆计算后得到最小序列 [0,1,2,3,4,5,6] ,然后返回偏移量为5的两个结果为 [5,6] 。

虽然Mycat返回了正确的结果,但是仔细推敲发现这类操作的处理逻辑是及其消耗(浪费)资源的。应用需要的结果集为2条,Mycat中需要处理的结果数为21条。也就是说,对于有 t 个DB节点的全分片 limit m, n 操作,Mycat需要处理的数据量为 (m+n)*t 个。比如实际应用中有50个DB节点,要执行limit 1000,10操作,则Mycat处理的数据量为 50500 条,返回结果集为10,当偏移量更大时,内存和CPU资源的消耗则是数十倍增加。

如果设计使用Mycat时有分页排序,请考虑放弃!

3.任意表JOIN

先看一下在单库中JOIN中的场景。假设在某单库中有 player 和 team 两张表,player 表中的 team_id 字段与 team 表中的id 字段相关联。操作场景如下图:

JOIN操作的SQL如下

mysql>selectp_name,t_name from player p, team t where p.no = 3 and p.team_id = t.id;

此时能查询出结果

如果将这两个表的数据分库后,相关联的数据可能分布在不同的DB节点上,如下图:

这个SQL在各个单独的分片DB中都查不出结果,也就是说Mycat不能查询出正确的结果集。

设计使用Mycat时如果要进行表JOIN操作,要确保两个表的关联字段具有相同的数据分布,否则请考虑放弃!

4.分布式事务

Mycat并没有根据二阶段提交协议实现 XA事务,而是只保证 prepare 阶段数据一致性的 弱XA事务 ,实现过程如下:

应用开启事务后Mycat标识该连接为非自动提交,比如前端执行

mysql>begin;

Mycat不会立即把命令发送到DB节点上,等后续下发SQL时,Mycat从连接池获取非自动提交的连接去执行。

Mycat会等待各个节点的返回结果,如果都执行成功,Mycat给该连接标识为 Prepare Ready 状态,如果有一个节点执行失败,则标识为 Rollback 状态。

执行完成后Mycat等待前端发送 commit 或 rollback 命令。发送 commit 命令时,Mycat检测当前连接是否为 Prepare Ready 状态,若是,则将 commit 命令发送到各个DB节点。

但是,这一阶段是无法保证一致性的,如果一个DB节点在 commit 时故障,而其他DB节点 commit 成功,Mycat会一直等待故障DB节点返回结果。Mycat只有收到所有DB节点的成功执行结果才会向前端返回 执行成功 的包,此时Mycat只能一直 waiting 直至TIMEOUT,导致事务一致性被破坏。

设计使用Mycat时如果有分布式事务,得先看是否得保证事务得强一致性,否则请考虑放弃!

参考:https://www.cnblogs.com/andy6/p/6622126.html

https://www.cnblogs.com/andy6/p/6622324.html

https://blog.csdn.net/gaobudong1234/article/details/79581846


猜你喜欢

转载自blog.csdn.net/actionzh/article/details/80903554
今日推荐