掌握6大模块7个核心概念!帮你搞定Mycat中间件
Posted 石杉的架构笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了掌握6大模块7个核心概念!帮你搞定Mycat中间件相关的知识,希望对你有一定的参考价值。
开篇
近今年里随着经济的飞速发展,企业的业务也在不断膨胀,作为业务支撑的信息系统特别是数据库系统也面临前所未有的压力,行业应用所产生的数据呈爆炸式地增长。数据从原来的GB级别迅速增常到TB甚至是PB的规模,已经远远超过传统计算技术的要求,原来集中式的存储方式已经无法满足数据存储的要求,此时分布式数据存储由于良好的透明性、数据冗余性、扩展性、自治性逐渐进入人们的视野。为了更好的使用和管理分布式数据库,业内推出了不少优秀的分布式数据库中间件,Mycat就是其中之一,今天就来看看Mycat的架构和实现原理。本篇文章会学到以下内容:
分布式数据存储与Mycat
Mycat架构介绍
Mycat核心概念及配置
分布式数据存储与Mycat
众所周知,在分布式数据库的使用场景下,数据的存储不像集中式数据库那样都存放在一台服务器的一个数据库中,而是会分布在不同的服务器的不同数据库中。而应用程序的会根据不同的数据库进行访问,如图1 所示,应用程序需要根据访问的数据库不同:数据库1、数据库2、数据库3使用不同的数据库连接,如果说某张数据表在三个数据库中都存在,也需要使用特定的方式对其进行访问,可以说在应用程序这端访问起来是比较麻烦的。
正因为应用程序在访问分布式数据库的时候会遇到类似的问题,所以引入了数据库中间件来简化应用程序需要面对的问题。如图2所示,在应用程序和数据库中间引入Mycat数据库中间件以后,让应用程序的编程更加方便,它不用在面对分布式的数据库,而只用针对Mycat中间件进行数据库编程就能完成对应的数据操作,并且适用于以下几种场景:
读写分离:可以通过Mycat针对数据库1进行写操作,而对数据库2和3进行读操作。如果在写服务器出现宕机的情况,Mycat可以将写的请求暂时转移到其他的数据库服务器上,保证数据库的可用性。
垂直分表分库:将订单表存放到数据库1和2中,将商品表存放到数据库3中。也就是把不同的表放在不同的库中。
水平分表分库:将订单表的不同记录通过分片算法(例如:hash取模)分表存放到数据库1和2中。也就是将相同表的不同数据放到不同库的表中。
访问不同的数据库:数据库1和2对应访问的就是mysql数据库,而数据库3访问的是Oracle数据库。
控制应用程序到数据库的连接数量:每一个数据库连接都会占用数据库服务器的资源,每个数据库服务器能够连接的请求也是有限的,这里Mycat可以控制前端应用请求数据库服务器的连接数量,保证数据库服务器的高可用。
换句话说,当应用程序发起一条SQL语句的时候,不用关心数据库存放在哪个服务器,以及数据库表是否做了分表分库,只用将要查的数据告诉Mycat就可以了,Mycat在考虑上述场景之后将结果返回给应用程序,让开发者更加方便快捷地操作数据。
上面描述的这些数据操作如果在没有Mycat中间件的情况需要在应用程序端维护大量的代码,而有了Mycat之后应用程序只需要针对Mycat进行配置,并且对其变成就能完成这些操作。
Mycat是一个开源的面相企业应用开发的数据库中间件,支持大数据库集群、事物、ACID。适用于高可用性、数据库读写分离、数据分级存储保障、大型数据库的分表分库以及并行计算、数据库路由以及整合诸如MySQL、Oracle、SQL Server 等数据库。由于Mycat开源中间件有一个发展的过程,每个版本的迭代都会遇到一些问题,目前已经更新到了Mycat 2.0是一个相对稳定的版本。
如果有条件的同学尽量使用最新版本,或者使用Mycat 1.6.5 以上的版本,其修正了一些常用SQL函数的问题。不过Mycat 也不是万能的依旧会存在一些问题,我们这里把它的优缺点列出如下表格方便大家参考。
优点 |
缺点 |
拆分后业务清晰,拆分规则明确 |
部分业务表无法join,只能通过接口调用 |
系统之间容易扩展和整合 |
跨库事务难以处理 |
数据维护简单 |
垂直切分后某些业务数据过于庞大,仍然存在单体性能瓶颈 |
解决了单库大数据、高并发的性能瓶颈 |
拆分规则很难抽象 |
拆分规则封装好,对应用端几乎透明,开发人员无需关心拆分细节 |
分片事务一致性难以解决,需要通过XA或者借助其他分布式事务方式,例如:Redis、Zookeeper。 |
提高了系统的稳定性和负载能力 |
二次扩展时,数据迁移、维护难度大 |
Mycat架构介绍
上面讲到了Mycat在分布式数据库中起到的作用,让应用程序的开发专注于业务本身,把分表分库、读写分离、访问不同数据以及控制数据库连接的问题都交给Mycat来处理。那么Mycat是通过怎样的架构实现上述功能的呢,下面就和我一起来看看Mycat的组件和架构。
从逻辑上划分以下六个模块。
通信协议模块:主要负责底层通信功能,例如收发数据、线程回调等工作。采用Reactor、Proctor模式,在网络IO架构中实现了NIO和AIO的方式。
SQL执行模块:顾名思义,其接受到要执行的SQL 以后通过数据库连接模块连接到数据库,通过连接池获取目标数据库,再经由SQL路由解析把SQL语句分发到数据库节点中进行执行。
路由解析模块:当Mycat实现分表分库功能的时候,路由就显得非常重要了。该模块当收到应用程序请求的查询语句以后,会连接后端的数据,通过配置文件的规则设置,将请求路由到对应的数据库的表中进行查询。同时该模块还肩负SQL解析的职能,需要对SQL语句的EXPLAIN、SET、SHOW、SELECT等命令进行解析,从而获取表名、条件、字段列表等信息。同时还可以对SQL语句进行改写。
数据库连接模块:主要负责创建、管理、维护后端的数据库以及对应的数据库连接池。并且通过连接池机制对数据库连接的生命周期进行管理。
结果集处理模块:当查询结果返回之前需要将其进行汇总、排序。特别是针对数据分片的情况,返回的数据来自不同的数据库服务器和表,需要将这些数据进行必要的汇总才能返回给应用程序。
监控管理模块:主要对Mycat中的连接、内存等资源进行监控和管理。监控参数包括:连接数、缓存命中数等。
上面六个模块看上去比较抽象,如果理清逻辑顺序记忆起来还是比较方便的。通讯协议模块接受到应用程序的SQL请求,会将其交给SQL执行模块,执行模块解析SQL之后需要知道访问哪些节点上的数据库。于是,它请求路由解析模块,再了解需要访问哪些数据库以后,通过数据库连接模块建立数据库连接,并且分发SQL到对应数据库上执行,将返回的数据通过结果集处理模块,汇总、排序,最后返回给应用程序。监控管理模块就好像一个大管家监视Mycat中的连接、内存等资源使用情况。
如果将上面的组件通过Mycat的处理流程展示的话:
如图3所示,整个图由上、中、下3步部分组成。
上面的部分代表客户端,其承载多个应用程序会向处在中间的Mycat服务发起SQL请求。中间Mycat服务,包含了上述的六大组件,负责对应用程序请求进行处理和响应。下面的存储层可以对接不同的数据源,为Mycat提供存储服务。整个请求处理流程分为请求和响应两个部分,分别由“从上往下”和“从下往上”的两个箭头代表,这里我们将Mycat的处理分为六个步骤给大家介绍如下:
1. 在客户端的应用程序向Mycat服务发起SQL请求的时候,通信协议模块会通过NIO/AIO的方式将请求提交给路由解析模块。
2. 路由解析模块包含SQL解析、优化和路由的功能。主要功能是将SQL进行解析成要执行的命令,并且对其进行优化,之后通过路由规则找到要执行的数据库服务器。
3. 之后请求会交给SQL执行模块,根据路由解析的结果分发到数据库服务器上执行。
4. 在执行之前需要通过数据库连接模块获取数据库对应的连接,同时需要对数据库连接池进行管理。
5. 同样,在分发执行SQL的时候也需要通信协议模块进行信息的传递。
6. 当执行完SQL请求以后,数据库会将数据通过结果处理模块进行聚合、排序、汇总的操作,最后将数据返回给客户端的应用程序,完成整个请求过程。
Mycat核心概念及配置
在描述完Mycat 的架构和工作流程以后,相信大家对Mycat的执行机制和结构都有一定的了解。站在架构的高度对下面的核心概念的理解会有一些帮助,如果说上面讲的是Mycat逻辑架构,那么下面介绍的核心概念及配置就涉及到具体操作的范畴。
毕竟Mycat需要提供配置工具完成开发者的功能,然后再通过架构来执行这些规则,最后实现对分布式数据库开发的透明性。接下来要介绍的就是在使用Mycat过程中遇到的核心概念,以及这些概念对应的配置方式和对应的配置文件。方便我们落地Mycat中间件的应用。
如图4所示,改图描述了Mycat 核心概念之间的关系,并且描述了这些核心概念在哪些配置文件中进行配置。
我们从上往下跟着序号来看这些概念:
Mycat中的系统信息和用户信息都在Server.xml文件中进行配置,其中对于user(用户)的配置包含了,用户基本信息和所能够访问schema(逻辑库)的权限。
Schema.xml包含了Mycat对于数据的定义,Schema(逻辑库)会包含一个或者多个table(逻辑表)。
Table(逻辑表)会通过包含的datanode(数据节点)来描述数据存放的服务器和物理数据库。
在datanode中包含了datahost和database。其中datahost表示数据库所在的服务器集群,而database是对物理数据库的描述。
针对每个table的分片定义规则,在rule.xml文件中进行定义,rule在定义规则的时候会调用function对规则算法进行描述。
上面我们将Mycat核心概念以及它们对应的配置文件给大家做了整体介绍,接下来将对上面的概念做深入的描述。
1.用户(User)
Mycat中的用户是一个逻辑上的用户,他定义了用来连接Mycat中间件的用户信息,并且将这些信息存放在server.xml文件中。如图5所示,这是server.xml 文件中对user 信息的定义。
可以看到定义了用户名为“test”,密码“password”是123456.在schemas 标签里面定义了“test_db” 这是该用户可以访问的逻辑数据库。在privileges标签中定义了true说明还会用户对逻辑库的具体使用权限。这里定义对“test_db”的dml到操作用的是四位数字表示,分别是“0110”。
实际上每一位都表示一种操作,四位对应的操作分别是“insert、update、select、delete”,如果对应的位数上是“1”表示支持该操作,如果是“0”表示不支持对应的操作。
“0110”就表示,不支持insert操作、支持update操作、支持select操作,不支持delete操作。以此类推在schema标签下面还有一个table标签,可以设置对逻辑表的权限,例如:table01的dml是0000,也就是不能进行四种操作的意思。
2.逻辑库(schema)
开发人员在进行数据库开发的时候都需要对某个具体的数据库进行操作,例如:查找、更新、删除等等。但是到了分布式数据库的时代,数据库以分布式的方式部署在不同的服务器节点中,此时再去访问这些数据库难度就增加了。有Mycat介入以后,引入了逻辑库的概念,逻辑库是一个概念上的定义,其背后对应的是一个或者多个实体数据库,它的定义是在schema.xml文件中进行的。
如图6所示:
定义了名为“test_db”的逻辑数据库。
sqlMaxLimit 用来限制每次查询数据能否返回的最大行数,这里设置的是“1000”,当为“-1”的时候就没有限制。
checkSQLschema 是一个是否通过库名和表名方式访问数据库的开关,默认情况下是“fasle”。
3.逻辑表(table)
既然有逻辑库就一定有逻辑表,通常意义上逻辑表会和物理表进行对应,有可能是一个逻辑表对应多个分布在不同数据节点的物理表;也有可能对应一张没有进行分片的物理表。同样这些配置都是在schema.xml配置文件中完成的。
如图7 所示:
在上面定义的逻辑库“test_db”中定义了一个逻辑表,表的名字叫做“order” ,逻辑表的名字需要和物理表的名字保持一致。因为在Mycat不会再定义逻辑表与物理表之间的关系了,因此使用这种隐性的方式让它们进行对应。
“primaryKey”标签是定义逻辑表的主键,逻辑表的主键和物理表的主键也是保持一致的。设置主键的目的是,如果在数据分片时没有选择主键,Mycat会通过这个定义主键的定义对物理表进行查询,从而提高查询的效率。
在“dataNode”标签中 定义了物理数据库的名字。如果一张物理表分片存储在多个物理数据库,那么每个物理数据库需要通过逗号进行分割。这里物理节点的顺序也就是索引的顺序。如图中显示的“orderdb01”的索引就是0,“orderdb02”的索引就是1。
最后在Rule标签中定义的是水平分片的规则,具体的定义方式在后面进行详细讲解。
4.数据节点(DataNode)
定义逻辑存储对应的物理数据库,这里包含两个重要的信息:
保存数据的数据库主机(集群)的名字
物理数据库的名称
同样在schema.xml配置文件的dataNode标签下配置。
如图8 所示:
“dataHost”标签描述了物理数据库的数据库服务器(服务器节点/集群)。
“database”标签描述了客户端物理数据库的名字,在服务器节点上必须存在这个数据库。
从两个数据节点(“orderdb01”,“orderdb02”)都定义到一个“mysql01”的datahost可以看出,它们的数据库都存放在同一个数据库集群中。
5.数据主机集群(DataHost)
数据主机集群主要是描述存放数据库的主机信息,通常来说是描述一个数据库服务器的集群。
如图9 所示:
dataHost中定义了“mysql01”的数据库主机集群,其中包括“maxCon”(最大连接数),“minCon”(最小连接数),“balance”(读写分离开关),“dbType”(数据库类型)等标签。
重要的是,在这个集群中定义了三台数据库的服务器。”192.168.0.1”这台是写服务器,与之对应有一台读服务器,它是“192.168.0.2”。另外,还有一台写服务器是”192.168.0.3”。
6.分片规则(TableRule)&函数(Function)
在schema.xml文件中基本都是数据方面的定义,其中在逻辑表中有针对rule的定义,这种情况是用来定义分片规则的,一般而言分片规则的定义在rule.xml文件中完成。
如图10所示:
图10
tableRule和function 定义
tableRule中定义了分片规则为“mod_3_order_id”,这个名字是给逻辑表中的rule标签使用的。从名字的含义可以看出,通过对3取模的方式对order_id这个字段进行计算,从而实现分片操作。
在columns标签中定义了order_id作为取模的字段。
在algorithm标签中定义了具体的分片算法。这里的算法名称可以从下面的function节点中找到对应的定义。
Function中的name 对应上面tablerule中的算法名称,同样是”mod_3”,也就是通过对3进行取模。
在class 标签中定义了算法实现的Class 类的namespace和对应的类名。
Count 标签定义的3就是具体取模的数字,这里是对3进行取模。
根据上面给出的配置规则的定义,可以得到图11所示分片规则。
当应用程序发起一个对order表的SQL查询,查询order_id=1的数据。
当请求提交给Mycat以后,针对简单取模的方式把order_id对3进行取模得到1。
由于order表被分片存放在DB0、DB1、DB2三个库中,通过取模的值路由到DB1的order表中并且执行SQL语句,完成这次分布式的查询。
总结
本文从分布式数据存储入手,描述了Mycat在分布式数据库中起到了怎样的作用。然后介绍了Mycat的六大模块:通信协议、SQL执行、路由解析、数据库连接、结果集处理、监控管理,是如何工作的。
最后通过介绍Mycat七大核心概念:用户、逻辑库、逻辑表、数据节点、数据主机集群、分片规则、分片函数,以及对应的三个配置文件:Server.xml、Schema.xml 和Rule.xml文件是如何帮助应用程序使用好Mycat中间件的。
END
征 稿
有酬投稿
以上是关于掌握6大模块7个核心概念!帮你搞定Mycat中间件的主要内容,如果未能解决你的问题,请参考以下文章