配置文件

server.xml

user 标签
1
2
3
4
5
6
7
<user name="zcy-fover">
<property name="schemas">mycattest1,mycatttest2</property>
<property name="password">123456</property>
<property name="readOnly">true</property>
<property name="benchmark">100</property>
<property name="usingDecrypt">1</property>
</user>
  • user 标签用于定义登录 mycat 的用户和权限,配置的用户只可以访问对应的 schema
  • schemas 可以配置多个 schema 用英文逗号分隔
  • readOnly 属性用来限制用户的读写权限
  • benchmark 属性限制前端的整体链接数量,置为 0 或者不设值则表示不限
  • usingDecrypt 属性表示开启密码加密功能,0:不开启,1:开启
system 标签
  • charset 字符集属性,配置时保证与 mysql 的一致
  • defaultSqlParser 指定默认的 sql 解析器
  • processors 指定系统可用的线程数量,默认值为机器 CPU 核心 x 每个核心运行线程的数量,processors 的值会影响 processorsBufferPool、processorsBufferLocalPersent、ProcessorsExecutor 和 NIOProcessor 属性
  • processorsBufferChunk 指定每次分配 Socket Direct Buffer 的默认字节是 4096,也会影响 bufferPool 的长度,如果一次性获取的字节过多导致 buffer 不够用,会出现告警,可以适当提高 processorsBufferChunk 的值
  • processorsBufferPool 指定 bufferPool 的计算比例,由于每次执行 NIO 读写都要使用到 buffer,所以 mycat 在初始化是会创建一定长度的 buffer 池来加快 NIO 读写效率,减少 buffer 的时间。
    • processorsBufferPool 的默认值:bufferChunkSize(4096) * processers * 1000
    • BufferPool 和 ThreadLocalPool 池,BufferPool 使用 ThreadLocalPool 作为二级缓存,每次从 BufferPool 获取时都会优先从 ThreadLocalPool 中获取 Buffer 的值,如果未命中,则会从 BufferPool 中获取,ThreadLocalPool 在每个线程内部使用,而 BufferPool 是每个 NIO 共享的。
    • BufferPool 的总长度为 BufferPool / BufferChunk,如果比值不是整数倍,则取整加一
  • processorBufferLocalPercent 控制 ThreadLocalPool 分配 Pool 的比例大小,该属性的默认值为 100
    • 线程缓存百分比 = BufferLocalPercent / processors
    • ThreadLocalPool 长度 = 线程缓存百分比 * BufferPool 长度 / 100
  • processorExecutor 指定 NIOProcessor 上共享 businessExecutor 固定线程池的大小,Mycat 把异步处理任务提交到这个 businessExecutor 线程池中
  • sequenceHandlerType 指定 Mycat 全局序列的类型,0:本地文件方式,1:数据库方式,2:时间戳序列方式。默认使用本地文件方式
  • TCP连接的相关属性 StandardSocketOptions.SO_RCVBUFStandardSocketOptions.SO_SNDBUFStandardSocketOptions.TCP_NODELAY对应到 mycat 的 TCP 连接配置如下:
    • frontSocketSoRcvbuf:默认值为 1024 * 1024
    • frontSocketSoSndbuf:默认值为 4 * 1024 *1024
    • frontSocketSoNoDelay:默认值为 1
    • backSocketSoRcvbuf:默认值为 4 * 1024 * 1024
    • backSocketSoSndbuf:默认值为 1024 *1024
    • backSocketSoNoDelay:默认值为 1
  • MySQL连接的相关属性
    • packetHeaderSize:指定 MySQL 协议中的报文长度,默认值为 4 个字节
    • maxPacketSize:指定 MySQL 协议可以携带的数据的最大值,默认值为 16MB
    • idleTimeout:指定连接的空闲时间的超时长度。如果某个连接的空闲时间超过 idleTimeout 的值,则该连接资源将被关闭并回收,单位毫秒,默认 30 分钟
    • charset:初始化连接字符集,默认 utf8
    • txIsolation:初始化前端连接事务的隔离级别,后续的 txIsolation 值为客户端的配置值。默认为 REPEATED_READ;READ_UNCOMMITTED: 1READ_COMMITTED: 2REPEATED_READ: 3SERIALIZABLE: 4
    • sqlExecuteTimeout:执行 SQL 语句的超时时间,若 SQL 执行超过这个时间,则会关闭连接,单位为秒,默认 300 秒
  • 心跳属性
    • processorCheckPeriod:清理 NIOProcessor 前后端连接空闲、超时、关闭连接的时间间隔,单位为毫秒,默认为 1 秒
    • dataNodeIdleCheckPeriod:对后端连接进行空闲、超时检查的时间间隔,单位为毫秒默认为 300 秒
    • dataNodeHeartbeatPeriod:对后端的所有读、写库发起心跳的时间间隔,单位为毫秒,默认为 10 秒
  • 服务相关属性
    • bindIp:服务监听的 IP 地址,默认值为 0.0.0.0
    • serverPort:定义 mycat 的使用端口,默认值为 8066
    • managerPort:定义 mycat 的管理端口,默认值为 9066
  • fakeMySQLVersion属性 mycat 使用 MySQL 的通信协议模拟了一个 MySQL 服务器,默认版本是 5.6
  • handleDistributedTransactions 分布式事务开关属性,
    • 值为0:不过滤分布式事务
    • 值为1:过滤分布式事务(如果分布式事务内只涉及全局表,则不过滤)
    • 值为2:不过滤分布式无,但是记录分布式事务日志
  • useOffHeapForMerge 该属性指定是否启用非堆内存处理跨分片结果集,1:开启,0:关闭
  • useGlobleTableCheck 全局表一致性检查,1:开启,0:关闭
  • useSQLStat 开启实时统计,1:开启,0:关闭
  • useCompression 是否开启 MySQL 压缩协议,1:开启,0:关闭
  • usingAIO 0:NIO,1:AIO
firewall标签

全局防火墙的设置,针对IP地址进行限制

1
2
3
4
5
6
7
8
<firewall> 
<whitehost>
<host host="127.0.0.1" user="mycat"/>
<host host="127.0.0.2" user="mycat"/>
</whitehost>
<blacklist check="false">
</blacklist>
</firewall>

schema.xml

mycat 的逻辑库、表、分片规则、分片节点及数据源相关配置项

schema 标签

定义逻辑库

1
2
3
4
5
6
<schema name="test1" checkSQLschema="false" sqlMaxLimit="100">
<table name="goods_order" subTables="goods_order$0-2" primaryKey="ID" autoIncrement="true" dataNode="dn1" rule="my-mod-long"/>
</schema>
<schema name="test2" checkSQLschema="false" sqlMaxLimit="100">
<table name="goods_order" subTables="goods_order$0-2" primaryKey="ID" autoIncrement="true" dataNode="dn1" rule="my-mod-long"/>
</schema>
  • name schema名称,需要在 server.xml 中定义后才可以
  • dataNode 配置逻辑库的默认分片,没有配置 table 标签则会分到默认的 dataNode;通过 mycat 建表,没有提前配置 table 标签,也没有配置默认 dataNode,则会报错
  • checkSQLSchema 当值为 true 时,sql 语句发送到数据库执行时,会去掉 schema,例如SELECT * FROM test1.user会变成SELECT * FROM user,如果语句所带的 schema 没有在schema标签中指定,则 mycat 不会去掉,在执行时如果没有定义该库则执行会出错。
  • sqlMaxLimit 拆分库情况下,限制返回数据的大小。例如设置为 100,当实际 sql 中没有使用 limit,在执行时,mycat 会自动加上 limit 100。如果在实际 sql 中写了 limit 语句,则该属性即时设置也无效。
table 标签

定义逻辑表

1
<table name="goods_order" subTables="goods_order$0-2" primaryKey="ID" autoIncrement="true" dataNode="dn1" rule="my-mod-long"/>
  • name 定义逻辑表的名称,和数据库中执行 create table 语句一样,同一个 schema 标签中,定义的表名必须唯一
  • dataNode 定义逻辑表所属的 dataNode,该值需要和 dataNode 标签中定义的一样,如果该表分布在多个 dataNode 上,可以如上类似使用 $ 符减少配置
  • rule 定义逻辑表使用的分表规则,该值需要在 rule.xml 文件中定义且需对应
  • ruleRequired 指定表是否绑定分片规则,如果设为true,但是没有指定 rule,则会报错
  • primaryKey 逻辑表对应真实表的主键。如果该属性配置的是真实表的主键,mycat 会缓存主键与 dataNode 的信息,再次使用主键查询时就不会广播式查询,直接路由到对应的 dataNode。但是如果缓存没有命中,还是会进行广播式查询。
  • type 定义逻辑表的类型,全局表:type 值是global;普通表:不指定该值为 global 的表
  • autoIncrement MySQL 对于非自增主键使用 last_insert_id() 不会返回结果,只会返回0,所以在 mycat 中使用该属性需要 MySQL 的表主键定义 auto_increment。使用该属性时配合数据库模式的全局序列使用
  • subTables 定义子表名称,目前在 mycat 1.6 版本后才支持分表,并且 dataNode 在分表条件下只能配置一个
  • needAddLimit 指定表是否需要在每个语句的后面加上 limit 限制,添加该属性后 mycat 会默认为查询语句后面添加 limit 100,如果 sql 语句中添加了 limit 限制,则该属性失效。该属性默认值为 true。
childTable 标签

定义 E-R 分片的子表,通过标签上的属性与父表关联,将有关联关系的父、子表放在同一个节点上,方便查询提高效率

  • name 子表名称
  • joinKey 插入子表时使用该属性查找父表存储的数据节点;该属性为子表的属性
  • parentKey 与父表建立关联关系的列名。首先获取 joinKey 再通过 parentKey 指定的列名产生查询语句,通过执行该查询语句知道父表在哪个分片上,从而确定子表的的存储位置;该属性是父表的属性
  • primaryKey 同 table 标签
  • needAddLimit 同 table 标签
dataNode 标签

定义 mycat 中的数据节点,一个 dataNode 标签就是一个独立的数据分片节点

1
<dataNode name="dn1" dataHost="mysql1" database="mycattest1"/>
  • name 定义 dataNode 的唯一名字,应用在 table 标签上的 dataNode 属性,建立表和数据节点的对应关系
  • dataHost 定义该数据分片所属的数据库实例,需要在 dataHost 标签中定义
  • dataBase 定义该分片所属数据库实例上的具体库,利用 实例+具体的库 两个维度定义分片,每个库上的表结构是一样的,这样可以方便对表进行水平拆分
dataHost 标签

定义数据库实例、读写分离和心跳

1
2
3
4
5
6
<dataHost name="mysql1" maxCon="1000" minCon="20" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM0" url="127.0.0.1:3306" user="test" password="123456">
<readHost host="hostS0" url="127.0.0.1:3306" user="test" password="123456"/>
</writeHost>
</dataHost>
  • name 定义 dataHost 标签的名称,在 dataNode 中使用
  • maxCon 每个读写实例连接池的最大连接数,内嵌标签 writeHost 和 readHost 都会使用这个值来初始化连接池的最大长度
  • minCon 每个读写实例连接池的最小连接数,初始化连接池大小
  • balance 负载均衡类型
    • balance=”0”:不开启读写分离机制,所有读操作发送到当前可用的 writeHost 上
    • balance=”1”:全部的 readHost 与 stand by writeHost 都参与当前 select 语句的负载均衡。即当为双主双从模式(M1->S1,M2->S2,并且M1,M2互为主备),正常情况下 M2、S1、S2都参与 select 语句的负载均衡
    • balance=”2”:所有的读操作都随机地分在 writeHost 和 readHost 上
    • balance=”3”:所有的读请求都随机分发到 writeHost 对应的 readHost 上,writeHost 不负载读压力。该配置在 mycat 1.3 后才有
  • dbType 指定后端连接的数据库类型,支持二进制的 MySQL 协议,还可以用 JDBC 连接 MongoDB、Oracle 等
  • dbDriver 指定连接后端使用的 Driver,可选 native 和 jdbc,因为 native 执行的是二进制的 MySQL 协议,所以可以使用 MySQL 和 MariaDB。其他类型的数据库需要使用 jdbc 驱动来支持,如果使用 jdbc,需要把支持 jdbc4 标准的驱动 jar 包放到 mycat 的 lib 文件夹下
  • switchType
    • -1:不自动切换
    • 1:默认值,表示自动切换
    • 2:基于 MySQL 主从同步的状态决定是否切换,心跳语句 show slave status
    • 3:基于 MySQL Galary Cluster 的切换机制(适合集群,用于 mycat 1.4.1及上),心跳语句show status like 'wsrep%'
  • tempReadHostAvailable 如果配置了 writeHost,下面的 readHost 依旧可用,默认值为 0
heartBeat 标签

指明用于后端数据库心跳检查的语句,例如 MySQL 可以使用select user(),Oracle 可以使用select 1 from dual,这个标签还有 connectionInitSql 属性,当使用 Oracle 需要执行初始化 SQL 的语句放到这里。

writeHost、readHost 标签

实例化后端连接池

  • host 标识不同的实例,writeHost 通常用 *M1;readHost 通常用 *S1
  • url 实例数据库连接地址,如果使用的是 native,一般为 address:port;使用 JDBC 或其他 dbDriver,需要自己指定;例如 JDBC示例:jdbc:MySQL://localhost:3306
  • user 后端存储实例的用户名
  • password 后端存储实例的密码
  • weight 在 readHost 中作为读节点的权重
  • usingDecrypt 开启密码加密功能,0:不开启,1:开启

rule.xml

分片规则配置文件, schema.xml 中 table 标签中的 rule 属性的值需要在 rule.xml 中配置

function 标签
1
2
3
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<property name="count">3</property>
</function>
  • name 指定算法的名称,在该文件中唯一
  • class 属性对应具体的分片算法,指定具体的算法类
  • property 根据算法要求指定
tableRule 标签
1
2
3
4
5
6
<tableRule name="my-mod-long">
<rule>
<columns>id</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
  • name 指定分片唯一算法名称
  • rule 分片算法具体内容
  • columns 对应表中用于分片的列名
  • algorithm function 中定义的算法名称

sequence 配置文件

分库分表情况下,数据库自增主键无法保证主键在集群中全局唯一,mycat 提供本地配置和数据库配置

本地文件方式

要启用这种方式,需要在 server.xml 配置文件中配置如下参数:

name
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

配置后,在 mycat 的conf目录下,在 sequence_conf.properties 配置如下参数:
```properties
COMPANY.MAXID=2000
GLOBAL.MAXID=20000
COMPANY.HISIDS=
CUSTOMER.MAXID=2000
HOTNEWS.CURID=1000
ORDER.MINID=1001
CUSTOMER.HISIDS=
HOTNEWS.MINID=1001
GLOBAL.CURID=10054
ORDER.MAXID=2000
COMPANY.CURID=1000
CUSTOMER.CURID=1000
COMPANY.MINID=1001
GLOBAL.MINID=10001
HOTNEWS.MAXID=2000
CUSTOMER.MINID=1001
GLOBAL.HISIDS=
HOTNEWS.HISIDS=
ORDER.HISIDS=
ORDER.CURID=1000

mycat 重新发布后配置文件中的 sequence 会恢复到初始值;优点是本地文件加载且读取速度快

数据库方式

在数据库中创建一张名为 sequence 的表,在 sequence_db_conf.properties 进行相关配置

  • sequence 获取步骤
    • 初次使用 sequence,根据传入的 sequence 民称从数据表中读取 current_value、increment 到 mycat 中,并做 current_value = current_value + increment
    • mycat 将读取到的 current_value + increment 作为本次使用的 sequence 值,下次使用时 sequence 自动加一,当使用 increment 次后,执行与步骤一相同的操作
    • mycat 负责维护这张表,用到那些 sequence 时,只需要在这张表中插入一条记录即可。若某次读取的 sequence 没有用完,系统宕机了,则本次已经读取未使用的 sequence 值会被丢弃
  • 数据库配置

创建表

1
2
3
4
5
6
7
8
9
#创建 sequence 表
CREATE TABLE IF NOT EXISTS sequence (
name VARCHAR(50) NOT NULL,
current_value INT NOT NULL,
increment INT NOT NULL DEFAULT 100,
PRIMARY KEY (name)
) ENGINE = InnoDB;
#初始化记录
INSERT INTO sequence (name, current_value, increment) VALUES ('GLOBAL', 10000, 100);

创建存储过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 获取当前sequence值
DROP FUNCTION IF EXISTS mycat_seq_currval;
DELIMITER $
CREATE FUNCTION mycat_seq_currval(seq_name VARCHAR(50)) RETURNS VARCHAR(64) CHARSET utf8
DETERMINISTIC
BEGIN
DECLARE retval VARCHAR(64);
SET retval = "-999999999,NULL";
SELECT concat(CAST(current_value AS CHAR), ",", CAST(increment AS CHAR)) INTO retval FROM sequence WHERE name = seq_name;
RETURN retval;
END $
DELIMITER ;

# 设置sequence值
DROP FUNCTION IF EXISTS mycat_seq_setval;
DELIMITER $
CREATE FUNCTION mycat_seq_setval(seq_name VARCHAR(50),value INTEGER) RETURNS VARCHAR(64) CHARSET utf8
DETERMINISTIC
BEGIN
UPDATE sequence SET current_value = value WHERE name = seq_name;
RETURN mycat_seq_currval(seq_name);
END $
DELIMITER ;

# 获取下一个sequence值
DROP FUNCTION IF EXISTS mycat_seq_nextval;
DELIMITER $
CREATE FUNCTION mycat_seq_nextval(seq_name VARCHAR(50)) RETURNS VARCHAR(64) CHARSET utf8
DETERMINISTIC
BEGIN
UPDATE sequence SET current_value = current_value + increment WHERE name = seq_name;
RETURN mycat_seq_currval(seq_name);
END $
DELIMITER ;
  • sequence_db_conf.properties 配置

指定 sequence 表所在的节点信息

1
2
3
4
5
#sequence stored in datanode
GLOBAL=dn1
COMPANY=dn1
CUSTOMER=dn1
ORDERS=dn1
本地时间戳方式

ID = 64 位二进制[42位(毫秒)+5位(机器ID)+5位(业务编码)+12位(重复累加)],换算成十进制 18 位数的 long 类型,每毫秒可以并发 12 位二进制的累加

  • 配置 server.xml
    1
    <property name="sequenceHandlerType">2</>
  • 配置 sequence_time_conf.properties
    • WORKID=0~31:可取 0 ~ 31 的任意整数
    • DATAACENTERID=0~31:可取 0 ~ 31 的任意整数
其他方式
  • 使用 catlet 注解
  • 使用 zookeeper 实现
自增长主键

利用 MySQL 数据库的自增主键功能,创建一个只有自增 ID 的表,在 table 标签中将 autoIncrement 置为 true,在 sequence_db_conf.properties 配置改数据表所在节点,在数据库的 sequence 表中增加该表的 sequence 记录

其他配置

缓存配置文件
1
2
3
4
5
6
7
#used for mycat cache service conf
factory.encache=io.mycat.cache.impl.EnchachePooFactory
#key is pool name ,value is type,max size, expire seconds
pool.SQLRouteCache=encache,10000,1800
pool.ER_SQL2PARENTID=encache,1000,1800
layedpool.TableID2DataNodeCache=encache,10000,18000
layedpool.TableID2DataNodeCache.TESTDB_ORDERS=50000,18000

factory.encache 指定缓存的实现类,不同的缓存实现类对应不同的缓存框架,后面的指定缓存的框架、缓存大小、过期时间

日志文件

配置日志的输出路径以及日志级别