【Mycat】Mycat 核心开发者带你看尽 Mycat 三大核心配置文件!!
写在前面
在分布式数据库中间件领域,Mycat 和 ShardingSphere 可以说是在开源界有着相当重要的位置,不少小伙伴也在问我:Mycat 和 sharding-jdbc 哪个好呀!其实,就我本身而言,我作为 Mycat 的开发者,也深度分析过 ShardingSphere 的源码。可以这么说:各有各的优势吧!其实,针对 ShardingSphere,我也跟 ShardingSphere 的创始人亮哥聊过,从他那里确实学到了不少有价值的东西。后续我也可能会写一部关于分布式数据库的书籍,也说不定会将 Mycat 和 ShardingSphere 写进去呢。到时肯定是要请亮哥帮我写推荐序呀!哈哈哈。。。
>
好了,说了这么多,今天给大家分享下 Mycat 的三大核心配置文件:server.xml、schema.xml 和 rule.xml。
server.xml
server.xml 几乎保存了所有 mycat 需要的系统配置信息。其在代码内直接的映射类为 SystemConfig 类。现在就对这个文件中的配置进行相关的介绍
user 标签
server.xml 中的标签本就不多,这个标签主要用于定义登录 mycat 的用户和权限。例如上面的例子中,我定义了一个用户,用户名为 test、密码也为 test,可访问的 schema 也只有 TESTDB 一个。如果我在 schema.xml 中定义了多个 schema,那么这个用户是无法访问其他的 schema。在 mysql 客户端看来则是无法使用 use 切换到这个其他的数据库。如果使用了 use 命令,则 mycat 会报出这样的错误提示:ERROR 1044 (HY000): Access denied for user 'test' to database 'xxx'这个标签嵌套的 property 标签则是具体声明的属性值,正如上面的例子。我们可以修改 user 标签的 name 属性来指定用户名;修改 password 内的文本来修改密码;修改 readOnly 为 true 或 false 来限制用户是否只是可读的;修改 schemas 内的文本来控制用户可放问的 schema;修改 schemas 内的文本来控制用户可访问的 schema,同时访问多个 schema 的话使用 , 隔开,例如:
system 标签
这个标签内嵌套的所有 property 标签都与系统配置有关,请注意,下面我会省去标签 property 直接使用这个标签的 name 属性内的值来介绍这个属性的作用。
defaultSqlParser 属性
由于 mycat 最初是时候 Foundation DB 的 sql 解析器,而后才添加的 Druid 的解析器。所以这个属性用来指定默认的解析器。目前的可用的取值有:druidparser 和 fdbparser。使用的时候可以选择其中的一种,目前一般都使用 druidparser。
processors 属性
这个属性主要用于指定系统可用的线程数,默认值为 Runtime.getRuntime().availableProcessors()方法返回的值。主要影响 processorBufferPool、processorBufferLocalPercent、processorExecutor 属性。NIOProcessor 的个数也是由这个属性定义的,所以调优的时候可以适当的调高这个属性。
processorBufferChunk 属性
这个属性指定每次分配 Socket Direct Buffer 的大小,默认是 4096 个字节。这个属性也影响 buffer pool 的长度。
processorBufferPool 属性
这个属性指定 bufferPool 计算 比例值。由于每次执行 NIO 读、写操作都需要使用到 buffer,系统初始化的时候会建立一定长度的 buffer 池来加快读、写的效率,减少建立 buffer 的时间。
两个主要的 buffer 池
BufferPool 和 ThreadLocalPool
BufferPool 由 ThreadLocalPool 组合而成,每次从 BufferPool 中获取 buffer 都会优先获取 ThreadLocalPool 中的 buffer,未命中之后才会去获取 BufferPool 中的 buffer。也就是说 ThreadLocalPool 是作为 BufferPool 的二级缓存,每个线程内部自己使用的。当然,这其中还有一些限制条件需要线程的名字是由 $_开头。然而,BufferPool 上的 buffer 则是每个 NIOProcessor 都共享的。默认这个属性的值为:
若 bufferPool 不是 bufferChunk 的整数倍,则总长度为前面计算得出的商 + 1 假设系统线程数为 4,其他都为属性的默认值,则:
processorBufferLocalPercent 属性
前面提到了 ThreadLocalPool。这个属性就是用来控制分配这个 pool 的大小用的,但其也并不是一个准确的值,也是一个比例值。这个属性默认值为 100。
例如,系统可以同时运行 4 个线程,使用默认值,则根据公式每个线程的百分比为 25。最后根据这个百分比来计算出具体的。
ThreadLocalPool 的长度公式如下:
假设 BufferPool 的长度为 4000,其他保持默认值。
那么最后每个线程建立上的 ThreadLocalPool 的长度为: 1000 = 25 * 4000 / 100
processorExecutor 属性
这个属性主要用于指定 NIOProcessor 上共享的 businessExecutor 固定线程池大小。mycat 在需要处理一些异步逻辑的时候会把任务提交到这个线程池中。新版本中这个连接池的使用频率不是很大了,可以设置一个较小的值。
sequnceHandlerType 属性
指定使用 Mycat 全局序列的类型。0 为本地文件方式,1 为数据库方式。默认是使用本地文件方式,文件方式主要只是用于测试使用。
TCP 连接相关属性
以上这三个属性,分别由:
frontSocketSoRcvbuf 默认值: 1024 * 1024
frontSocketSoSndbuf 默认值: 4 1024 1024
frontSocketNoDelay 默认值: 1
backSocketSoRcvbuf 默认值: 4 1024 1024
backSocketSoSndbuf 默认值: 1024 * 1024
backSocketNoDelay 默认值: 1
各自设置前后端 TCP 连接参数。Mycat 在每次建立前、后端连接的时候都会使用这些参数初始化连接。可以按系统要求适当的调整这些 buffer 的大小。TCP 连接参数的定义,可以查看 Javadoc。
MySQL 连接相关属性初始化 mysql 前后端连接所涉及到的一些属性:
packetHeaderSize : 指定 Mysql 协议中的报文头长度。默认 4。
maxPacketSize : 指定 Mysql 协议可以携带的数据最大长度。默认 16M。
idleTimeout : 指定连接的空闲超时时间。某连接在发起空闲检查下,发现距离上次使用超过了空闲时间,那么这个连接会被回收,就是被直接的关闭掉。默认 30 分钟。
charset : 连接的初始化字符集。默认为 utf8。
txIsolation : 前端连接的初始化事务隔离级别,只在初始化的时候使用,后续会根据客户端传递过来的属性对后端数据库连接进行同步。默认为 REPEATED_READ。
sqlExecuteTimeout:SQL 执行超时的时间,Mycat 会检查连接上最后一次执行 SQL 的时间,若超过这个时间则会直接关闭这连接。默认时间为 300 秒。
周期间隔相关属性
mycat 中有几个周期性的任务来异步的处理一些我需要的工作。这些属性就在系统调优的过程中也是比不可少的。
processorCheckPeriod : 清理 NIOProcessor 上前后端空闲、超时和关闭连接的间隔时间。默认是 1 秒。
dataNodeIdleCheckPeriod : 对后端连接进行空闲、超时检查的时间间隔,默认是 60 秒。
dataNodeHeartbeatPeriod : 对后端所有读、写库发起心跳的间隔时间,默认是 10 秒。
服务相关属性
这里介绍一个与服务相关的属性,主要会影响外部系统对 myact 的感知。
bindIp : mycat 服务监听的 IP 地址,默认值为 0.0.0.0。
serverPort : 定义 mycat 的使用端口,默认值为 8066。
managerPort : 定义 mycat 的管理端口,默认值为 9066。
schema.xml
schema.xml 作为 MyCat 中重要的配置文件之一,管理着 MyCat 的逻辑库、表、分片规则、DataNode 以及 DataSource。弄懂这些配置,是正确使用 MyCat 的前提。这里就一层层对该文件进行解析。
schema 标签
dataNode
该属性用于绑定逻辑库到某个具体的 database 上,如果定义了这个属性,那么这个逻辑库就不能工作在分库分表模式下了。也就是说对这个逻辑库的所有操作会直接作用到绑定的 dataNode 上,这个 schema 就可以用作读写分离和主从切换,具体如下配置:
那么现在 USERDB 就绑定到 dn1 所配置的具体 database 上,可以直接访问这个 database。当然该属性只能配置绑定到一个 database 上,不能绑定多个 dn。
checkSQLschema
当该值设置为 true 时,如果我们执行语句 *select from TESTDB.travelrecord; 则 MyCat 会把语句修改为 select * from travelrecord; 。即把表示 schema 的字符去掉,避免发送到后端数据库执行时报 (ERROR 1146 (42S02): Table ‘testdb.travelrecord’ doesn’t exist)。 不过,即使设置该值为 true ,如果语句所带的是并非是 schema 指定的名字,例如: select from db1.travelrecord;* 那么 MyCat 并不会删除 db1 这个字段,如果没有定义该库的话则会报错,所以在提供 SQL 语句的最好是不带这个字段。
sqlMaxLimit
当该值设置为某个数值时。每条执行的 SQL 语句,如果没有加上 limit 语句,MyCat 也会自动的加上所对应的值。例如设置值为 100,执行 *select from TESTDB.travelrecord; 的效果为和执行 select from TESTDB.travelrecord limit 100;* 相同。不设置该值的话,MyCat 默认会把查询到的信息全部都展示出来,造成过多的输出。所以,在正常使用中,还是建议加上一个值,用于减少过多的数据返回。当然 SQL 语句中也显式的指定 limit 的大小,不受该属性的约束。
table 标签
Table 标签定义了 MyCat 中的逻辑表,所有需要拆分的表都需要在这个标签中定义。
name 属性
定义逻辑表的表名,这个名字就如同我在数据库中执行 create table 命令指定的名字一样,同个 schema 标签中定义的名字必须唯一。
dataNode 属性
定义这个逻辑表所属的 dataNode, 该属性的值需要和 dataNode 标签中 name 属性的值相互对应。如果需要定义的 dn 过多可以使用如下的方法减少配置:
这里需要注意的是 database 属性所指定的真实 database name 需要在后面添加一个,例如上面的例子中,我需要在真实的 mysql 上建立名称为 dbs0 到 dbs99 的 database。
rule 属性
该属性用于指定逻辑表要使用的规则名字,规则名字在 rule.xml 中定义,必须与 tableRule 标签中 name 属性属性值一一对应。
primaryKey 属性
该逻辑表对应真实表的主键,例如:分片的规则是使用非主键进行分片的,那么在使用主键查询的时候,就会发送查询语句到所有配置的 DN 上,如果使用该属性配置真实表的主键。难么 MyCat 会缓存主键与具体 DN 的信息,那么再次使用非主键进行查询的时候就不会进行广播式的查询,就会直接发送语句给具体的 DN,但是尽管配置该属性,如果缓存并没有命中的话,还是会发送语句给具体的 DN,来获得数据。
type 属性
该属性定义了逻辑表的类型,目前逻辑表只有“全局表”和”普通表”两种类型。对应的配置:全局表:global。普通表:不指定该值为 globla 的所有表。
autoIncrement 属性
MySQL 对非自增长主键,使用 lastinsertid()是不会返回结果的,只会返回 0。所以,只有定义了自增长主键的表才可以用 lastinsertid()返回主键值。mycat 目前提供了自增长主键功能,但是如果对应的 mysql 节点上数据表,没有定义 autoincrement,那么在 mycat 层调用 lastinsertid()也是不会返回结果的。由于 insert 操作的时候没有带入分片键,mycat 会先取下这个表对应的全局序列,然后赋值给分片键。这样才能正常的插入到数据库中,最后使用 lastinsert_id()才会返回插入的分片键值。如果要使用这个功能最好配合使用数据库模式的全局序列。使用 autoIncrement=“true” 指定这个表有使用自增长主键,这样 mycat 才会不抛出分片键找不到的异常。使用 autoIncrement=“false” 来禁用这个功能,当然你也可以直接删除掉这个属性。默认就是禁用的。
needAddLimit 属性
指定表是否需要自动的在每个语句后面加上 limit 限制。由于使用了分库分表,数据量有时会特别巨大。这时候执行查询语句,如果恰巧又忘记了加上数量限制的话。那么查询所有的数据出来,也够等上一小会儿的。所以,mycat 就自动的为我们加上 LIMIT 100。当然,如果语句中有 limit,就不会在次添加了。这个属性默认为 true,你也可以设置成 false`禁用掉默认行为。
childTable 标签
childTable 标签用于定义 E-R 分片的子表。通过标签上的属性与父表进行关联
name 属性
定义子表的表名。
joinKey 属性
插入子表的时候会使用这个列的值查找父表存储的数据节点。
parentKey 属性
属性指定的值一般为与父表建立关联关系的列名。程序首先获取 joinkey 的值,再通过 parentKey 属性指定的列名产生查询语句,通过执行该语句得到父表存储在哪个分片上。从而确定子表存储的位置。
primaryKey 属性
同 table 标签所描述的。
needAddLimit 属性
同 table 标签所描述的。
dataNode 标签
dataNode 标签定义了 MyCat 中的数据节点,也就是我们通常说所的数据分片。一个 dataNode 标签就是一个独立的数据分片。例子中所表述的意思为:使用名字为 lch3307 数据库实例上的 db1 物理数据库,这就组成一个数据分片,最后,我们使用名字 dn1 标识这个分片。
name 属性
定义数据节点的名字,这个名字需要是唯一的,我们需要在 table 标签上应用这个名字,来建立表与分片对应的关系。
dataHost 属性
该属性用于定义该分片属于哪个数据库实例的,属性值是引用 dataHost 标签上定义的 name 属性。
database 属性
该属性用于定义该分片属性哪个具体数据库实例上的具体库,因为这里使用两个纬度来定义分片,就是:实例+具体的库。因为每个库上建立的表和表结构是一样的。所以这样做就可以轻松的对表进行水平拆分。
dataHost 标签
作为 Schema.xml 中最后的一个标签,该标签在 mycat 逻辑库中也是作为最底层的标签存在,直接定义了具体的数据库实例、读写分离配置和心跳语句。现在我们就解析下这个标签。
name 属性
唯一标识 dataHost 标签,供上层的标签使用。
maxCon 属性
指定每个读写实例连接池的最大连接。也就是说,标签内嵌套的 writeHost、readHost 标签都会使用这个属性的值来实例化出连接池的最大连接数。
minCon 属性
指定每个读写实例连接池的最小连接,初始化连接池的大小。
balance 属性
balance=“0”, 所有读操作都发送到当前可用的 writeHost 上。
balance=“1”,所有读操作都随机的发送到 readHost。
balance=“2”,所有读操作都随机的在 writeHost、readhost 上分发。
writeType 属性
负载均衡类型,目前的取值有 3 种:
writeType=“0”, 所有写操作都发送到可用的 writeHost 上。
writeType=“1”,所有写操作都随机的发送到 readHost。
writeType=“2”,所有写操作都随机的在 writeHost、readhost 分上发。
dbType 属性
指定后端连接的数据库类型,目前支持二进制的 mysql 协议,还有其他使用 JDBC 连接的数据库。例如:mongodb、oracle、spark 等。
dbDriver 属性
指定连接后端数据库使用的 Driver,目前可选的值有 native 和 JDBC。使用 native 的话,因为这个值执行的是二进制的 mysql 协议,所以可以使用 mysql 和 maridb。其他类型的数据库则需要使用 JDBC 驱动来支持。如果使用 JDBC 的话需要将符合 JDBC 4 标准的驱动 JAR 包放到 MYCAT\lib 目录下,并检查驱动 JAR 包中包括如下目录结构的文件:META-INF\services\java.sql.Driver。在这个文件内写上具体的 Driver 类名,例如:com.mysql.jdbc.Driver。
heartbeat 标签
这个标签内指明用于和后端数据库进行心跳检查的语句。例如,MYSQL 可以使用 select user(),Oracle 可以使用 select 1 from dual 等。这个标签还有一个 connectionInitSql 属性,主要是当使用 Oracla 数据库时,需要执行的初始化 SQL 语句就这个放到这里面来。例如:alter session set nlsdateformat='yyyy-mm-dd hh24:mi:ss'
writeHost 标签、readHost 标签
这两个标签都指定后端数据库的相关配置给 mycat,用于实例化后端连接池。唯一不同的是,writeHost 指定写实例、readHost 指定读实例,组着这些读写实例来满足系统的要求。在一个 dataHost 内可以定义多个 writeHost 和 readHost。但是,如果 writeHost 指定的后端数据库宕机,那么这个 writeHost 绑定的所有 readHost 都将不可用。另一方面,由于这个 writeHost 宕机系统会自动的检测到,并切换到备用的 writeHost 上去。这两个标签的属性相同,这里就一起介绍。
host 属性
用于标识不同实例,一般 writeHost 我们使用 M1,readHost 我们用 S1。
url 属性
后端实例连接地址,如果是使用 native 的 dbDriver,则一般为 address:port 这种形式。用 JDBC 或其他的 dbDriver,则需要特殊指定。当使用 JDBC 时则可以这么写:jdbc:mysql://localhost:3306/。
user 属性
后端存储实例需要的用户名字
password 属性
后端存储实例需要的密码
rule.xml
rule.xml 里面就定义了我们对表进行拆分所涉及到的规则定义。我们可以灵活的对表使用不同的分片算法,或者对表使用相同的算法但具体的参数不同。这个文件里面主要有 tableRule 和 function 这两个标签。在具体使用过程中可以按照需求添加 tableRule 和 function。
tableRule 标签
这个标签定义表规则。定义的表规则,在 rule.xml:
name 属性指定唯一的名字,用于标识不同的表规则。内嵌的 rule 标签则指定对物理表中的哪一列进行拆分和使用什么路由算法。columns 内指定要拆分的列名字。algorithm 使用 function 标签中的 name 属性。连接表规则和具体路由算法。当然,多个表规则可以连接到同一个路由算法上。标签内使用。让逻辑表使用这个规则进行分片。
function 标签
其中,各属性如下所示。
name 指定算法的名字。
class 制定路由算法具体的类名字。
property 为具体算法需要用到的一些属性。
好了,今天就到这儿吧,我是冰河,我们下期见!!
原创 PDF
冰河写的原创 PDF 都在这儿了:涵盖高并发编程、并发编程源码解析、限流、设计模式、Java8 新特性、分布式存储、Nginx 技术、互联网工程技术等,每一部 PDF 都是超硬核的技术干货。现都免费开源,详情参见《肝了三天三夜整理出这份36万字全网最牛的开源高并发编程PDF!!》文末附各 PDF 下载方式。
重磅福利
微信搜一搜【冰河技术】微信公众号,关注这个有深度的程序员,每天阅读超硬核技术干货,公众号内回复【PDF】有我准备的一线大厂面试资料和我原创的超硬核 PDF 技术文档,以及我为大家精心准备的多套简历模板(不断更新中),希望大家都能找到心仪的工作,学习是一条时而郁郁寡欢,时而开怀大笑的路,加油。如果你通过努力成功进入到了心仪的公司,一定不要懈怠放松,职场成长和新技术学习一样,不进则退。如果有幸我们江湖再见!
另外,我开源的各个 PDF,后续我都会持续更新和维护,感谢大家长期以来对冰河的支持!!
写在最后
如果你觉得冰河写的还不错,请微信搜索并关注「 冰河技术 」微信公众号,跟冰河学习高并发、分布式、微服务、大数据、互联网和云原生技术,「 冰河技术 」微信公众号更新了大量技术专题,每一篇技术文章干货满满!不少读者已经通过阅读「 冰河技术 」微信公众号文章,吊打面试官,成功跳槽到大厂;也有不少读者实现了技术上的飞跃,成为公司的技术骨干!如果你也想像他们一样提升自己的能力,实现技术能力的飞跃,进大厂,升职加薪,那就关注「 冰河技术 」微信公众号吧,每天更新超硬核技术干货,让你对如何提升技术能力不再迷茫!
版权声明: 本文为 InfoQ 作者【冰河】的原创文章。
原文链接:【http://xie.infoq.cn/article/8848a154724a7fc610acb5d70】。文章转载请联系作者。
评论