MyCat应用实战
下载Mycat
https://github.com/MyCATApache/Mycat-Server/releases
Mycat基础分库
基础配置
- 修改server.xml
<user name="root" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>
<property name="defaultSchema">TESTDB</property>
<!--No MyCAT Database selected 错误前会尝试使用该schema作为schema,不设置则为null,报错 -->
<!-- 表级 DML 权限设置 -->
<!--
<privileges check="false">
<schema name="TESTDB" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table>
</schema>
</privileges>
-->
</user>
可以修改用户名和密码以及逻辑库名。另外将全局主键改为文件的方式,将下面的1改为0.
<property name="sequenceHandlerType">1</property>
- 修改schema.xml
修改了数据库名,数据库用户密码
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
<table name="position" primaryKey="id" dataNode="dn1,dn2" rule="sharding-by-intfile" autoIncrement="true" >
</table>
</schema>
<dataNode name="dn1" dataHost="localhost1" database="ds_0" />
<dataNode name="dn2" dataHost="localhost1" database="ds_1" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="jdbc:mysql://localhost:3306" user="root"
password="0490218292">
</writeHost>
</dataHost>
</mycat:schema>
- 配置rule.xml
rule.xml里定义了很多分片规则,我们选择最简单的取模分片mod-long,只需要将这个名称配置到schema.xml里就行了。另外因为我们只有2个节点,所以取余的数量需要将3改为2。
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">3</property>
</function>
将mod-long配置到rule里。
<table name="position" primaryKey="id" dataNode="dn1,dn2" rule="mod-long" autoIncrement="true" >
</table>
启动
在mycat/bin目录下,用管理员身份启动cmd,执行如下命令:
mycat install
mycat start
启动完成后,就可以进行访问了。
命令行方式:
mysql -uroot -p123456 -h127.0.0.1 -P8066
测试
插入数据测试:
INSERT INTO POSITION (id,NAME,salary,city) VALUES(1,"lagou3","1222","sichuan");
INSERT INTO POSITION (id,NAME,salary,city) VALUES(2,"lagou3","1222","sichuan");
INSERT INTO POSITION (id,NAME,salary,city) VALUES(3,"lagou3","1222","sichuan");
INSERT INTO POSITION (id,NAME,salary,city) VALUES(4,"lagou3","1222","sichuan");
数据是否分布到了ds_0、ds_1两个库中。
查询:
select * from POSITION;
看能否查出两个库中的所有数据。
碰到的问题
问题1:因为我是mysql8,所以在mycat/lib中用mysql-connector-java-8.0.11.jar替换了原有的.
问题2:The server time zone value '???ú±ê×??±??' is unrecognized or represents more than one time zone
<writeHost host="hostM1" url="jdbc:mysql://localhost:3306?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8" user="root"
password="0490218292">
</writeHost>
url配置里加上了时区。
此外mycat还有如下命令:
启动命令:./mycat start
停止命令:./mycat stop
重启命令:./mycat restart
查看状态:./mycat status
全局序列ID
全局序列id有5种方式可以选择。
在server.xml里有如下配置:
<property name="sequenceHandlerType">0</property>
- 0 代表本地文件方式
- 1 代表数据库方式生成
- 2 代表使用本地时间戳方式
- 3 表示基于ZK与本地配置的分布式ID生成器
- 4 使用zookeeper递增方式生成
1. 本地文件方式
本地主键的配置文件是conf/sequence_conf.properties。
#default global sequence
GLOBAL.HISIDS=
GLOBAL.MINID=10001
GLOBAL.MAXID=20000
GLOBAL.CURID=10000
# self define sequence
COMPANY.HISIDS=
COMPANY.MINID=1001
COMPANY.MAXID=2000
COMPANY.CURID=1000
CUSTOMER.HISIDS=
CUSTOMER.MINID=1001
CUSTOMER.MAXID=2000
CUSTOMER.CURID=1000
ORDER.HISIDS=
ORDER.MINID=1001
ORDER.MAXID=2000
ORDER.CURID=1000
HOTNEWS.HISIDS=
HOTNEWS.MINID=1001
HOTNEWS.MAXID=2000
HOTNEWS.CURID=1000
我们默认在进行插入的时候就会使用mycat的全局主键生成,那么上面有那么多的配置项,具体取哪一个配置项呢?
这个配置的前缀是跟表名对应的。举例说明:
<table name="position" primaryKey="id" dataNode="dn1,dn2" rule="mod-long" autoIncrement="true" >
</table>
比如这个表,就需要配置如下:
POSITION.HISIDS=
POSITION.MINID=1
POSITION.MAXID=20000
POSITION.CURID=0
这样,在我们不指定id进行插入时就可以取我们配置的序列号了。
INSERT INTO POSITION (NAME,salary,city) VALUES("lagou3","1222","sichuan");
当然也可以显示指定取哪一个序列号配置:
INSERT INTO POSITION (id,NAME,salary,city) VALUES('next value for MYCATSEQ_GLOBAL',"lagou3","1222","sichuan");
MYCATSEQ_ 后面连接的就是配置前缀名称。
2. 数据库方式
配置文件是conf/sequence_db_conf.properties,里面需要配置db的id相关的配置信息存在哪个库中。
#sequence stored in datanode
GLOBAL=dn1
COMPANY=dn1
CUSTOMER=dn1
ORDERS=dn1
此处的dn1是逻辑库名。
我们需要在dn1对应的数据库中新建表,并且插入数据。Mycat给我们提供了建表等语句(conf/dbseq.sql)。我们执行即可。
increment字段表示一次从数据库取几个值。比如设置为10的话,就是一次取10个id供应用端使用。
3. 时间戳方式
配置文件是conf/sequence_time_conf.properties。
#sequence depend on TIME
WORKID=01
DATAACENTERID=01
全局表配置
只需要在schema.xml的配置中加上type=global就行了
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
<table name="city" primaryKey="id" dataNode="dn1,dn2" autoIncrement="true" type="global" >
</table>
</schema>
读写分离
通过writeHost 和readHost 实现
<dataHost name="localhost2" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="jdbc:mysql://localhost:3306?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8" user="root"
password="0490218292">
<readHost host="hostS1" url="jdbc:mysql://192.168.56.115:3306?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8" user="root"
password="123456">
</readHost>
</writeHost>
</dataHost>
或者
<dataHost name="localhost2" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="jdbc:mysql://localhost:3306?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8" user="root"
password="0490218292">
</writeHost>
<writeHost host="hostS1" url="jdbc:mysql://192.168.56.115:3306?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8" user="root"
password="123456">
</writeHost>
</dataHost>
两种方式对比:
- 第一种配置方式,如果写节点挂了,读节点不可用。
- 第二种配置方式(查询的时候取第二个writeHost),如果其中一个写节点挂了,另一个不受影响。
如果设置全库的读写分离,schema.xml配置如下:
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn3">
</schema>
<dataNode name="dn3" dataHost="localhost2" database="crm" />
<dataHost name="localhost2" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="jdbc:mysql://localhost:3306?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8" user="root"
password="0490218292">
<readHost host="hostS1" url="jdbc:mysql://192.168.56.115:3306?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8" user="root"
password="123456">
</readHost>
</writeHost>
</dataHost>
</mycat:schema>
此时里不能配置表的一些配置数据。
如果设置某些表(示例中是dept)读写分离,配置如下:
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
<table name="position" primaryKey="id" dataNode="dn1,dn2" rule="mod-long" autoIncrement="true" >
</table>
<table name="city" primaryKey="id" dataNode="dn1,dn2" autoIncrement="true" type="global" >
</table>
<table name="dept" primaryKey="id" dataNode="dn3" autoIncrement="true" ruleRequired="false">
</table>
</schema>
<dataNode name="dn1" dataHost="localhost1" database="ds_0" />
<dataNode name="dn2" dataHost="localhost1" database="ds_1" />
<dataNode name="dn3" dataHost="localhost2" database="crm" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="jdbc:mysql://localhost:3306?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8" user="root"
password="0490218292">
</writeHost>
</dataHost>
<dataHost name="localhost2" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="jdbc:mysql://localhost:3306?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8" user="root"
password="0490218292">
<readHost host="hostS1" url="jdbc:mysql://192.168.56.115:3306?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8" user="root"
password="123456">
</readHost>
</writeHost>
</dataHost>
</mycat:schema>
强制路由
通过mycat的注释实现:
/*#mycat:db_type=slave*/ SELECT * FROM dept;
/*#mycat:db_type=master*/ SELECT * FROM dept;
1.6版本后,还有如下注释:
/*!mycat:sql=sql */ 指定真正执行的SQL
/*!mycat:schema=schema1 */ 指定走那个schema
/*!mycat:datanode=dn1 */ 指定sql要运行的节点
/*!mycat:catlet=io.mycat.catlets.ShareJoin */ 通过catlet支持跨分片复杂SQL实现以及存
储过程支持等
主从延时切换
switchType参数:
- -1:表示不自动切换
- 1:表示自动切换
- 2:表示基于Mysql主从同步状态决定是否切换
- 3:基于Mysql cluster集群切换机制
1.4版本后开始支持MySQL主从复制状态绑定的读写分离机制,让读操作更加安全可靠。需要配置内容如下:
MyCAT心跳检查语句配置为 show slave status,dataHost上定义两个新属性:switchType="2"与slaveThreshold="100"
此时意味着开启 MySQL 主从复制状态绑定的读写分离与切换机制,Mycat心
跳机制通过检测 show slave status 中的 "Seconds_Behind_Master", "Slave_IO_Running",
"Slave_SQL_Running" 三个字段来确定当前主从同步的状态以及 Seconds_Behind_Master 主从复制时延, 当Seconds_Behind_Master > slaveThreshold时,读写分离筛选器会过滤掉此Slave机器,防止读到很久之前的旧数据,而当主节点宕机后,切换逻辑会检查Slave上的Seconds_Behind_Master是否为0,为0时则表示主从同步,可以安全切换,否则不会切换
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" writeType="0"
dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
<heartbeat>show slave status </heartbeat>
<!-- can have multi write hosts -->
<writeHost host="M1" url="localhost:3306" user="root" password="123456">
</writeHost>
<writeHost host="S1" url="localhost:3316" user="root"
</dataHost>
1.4.1开始支持MySQL集群模式:
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" writeType="0"
dbType="mysql" dbDriver="native" switchType="3" >
<heartbeat> show status like ‘wsrep%’</heartbeat>
<writeHost host="M1" url="localhost:3306" user="root"password="123456">
</writeHost>
<writeHost host="S1"url="localhost:3316"user="root"password="123456" >
</writeHost>
</dataHost>
XA事务使用
Mycat 从 1.6.5 版本开始支持标准XA分布式事务,考虑到MySQL5.7之前版本XA有bug,所以推荐最佳搭配XA功能使用 MySQL 5.7 版本。
Mycat实现XA标准分布式事务,Mycat作为XA事务协调者角色,即使事务过程中Mycat宕机挂掉,由于Mycat会记录事务日志,所以Mycat恢复后会进行事务的恢复善后处理工作。考虑到分布式事务的性能开销比较大,所以只推荐在全局表的事务以及其他一些对一致性要求比较高的场景。
使用示例:
- XA事务需要设置手动提交
set autocommit=0;
- 开启XA事务
set xa=on;
- 执行相应的SQL语句部分
insert into city(id,name,province) values(200,'chengdu','sichuan');
update position set salary='300000' where id<5;
- 提交或回滚事务
commit;
rollback;
如果其中一个sql语句失败,整体都会回滚。
保证Repeatable Read
mycat 有一个特性,就是开事务之后,如果不运行 update/delete/select for update 等更新类语句SQL 的话,不会将当前连接与当前 session 绑定。如下图所示:

这样做的好处是可以保证连接可以最大限度的复用,提升性能。但是回导致两次查询的结果不一致。违背了MySQL可重复读的特性。Mycat给我们提供了一个配置来解决这个问题。
server.xml 的 system 配置了 strictTxIsolation=true)(默认是false) 的时候,就会严格遵守隔离级别。配置后的连接如下图所示:

MyCat应用实战的更多相关文章
- 一步一步在Windows中使用MyCat负载均衡
一步一步在Windows中使用MyCat负载均衡 http://www.cnblogs.com/zhangs1986/p/6408981.html mycat+sqlServer简单demo配置 ...
- MyCAT+MySQL搭建高可用企业级数据库集群视频课程
原文地址:https://www.guangboyuan.cn/mycatmysql%E6%90%AD%E5%BB%BA%E9%AB%98%E5%8F%AF%E7%94%A8%E4%BC%81%E4% ...
- 【无私分享:ASP.NET CORE 项目实战(第十三章)】Asp.net Core 使用MyCat分布式数据库,实现读写分离
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 MyCat2.0版本很快就发布了,关于MyCat的动态和一些问题,大家可以加一下MyCat的官方QQ群:106088787.我 ...
- 15套java架构师、集群、高可用、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战视频教程
* { font-family: "Microsoft YaHei" !important } h1 { color: #FF0 } 15套java架构师.集群.高可用.高可扩展. ...
- 15套java架构师、集群、高可用、高可扩 展、高性能、高并发、性能优化Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战视频教程
* { font-family: "Microsoft YaHei" !important } h1 { color: #FF0 } 15套java架构师.集群.高可用.高可扩 展 ...
- [Big Data - Codis, Mycat(cobar)] 企业互联网+转型实战:如何进行PB级别数据的架构变迁
随着DT时代的来临,数据对于企业经营决策的价值日益凸显,而企业在进行互联网+转型的过程中,如何让数据架构平滑迁移到大数据平台,对于传统业务的转型升级至关重要.企业IT部门该如何进行PB级别大数据平台的 ...
- mycat实战之性能测试
1.安装性能监控工具 1.1 nmon 安装nmon de >#下载地址 http://nmon.sourceforge.net/pmwiki.php?n=Site.Download nmon1 ...
- Mycat实战之数据迁移(oracle -- mysql)
1.案例场景: Mycat 后面接一个 Oracle 实例与一个 MySQL 实例,假设用户表,订单表,转账记录表, Oracle 字符集为 GBK 的,MySQL 字符集则要求 UTF8的 完成用户 ...
- MYCAT实战之分片迁移
实践扩容 1.要求: travelrecord 表定义为10个分片,尝试将10个分片中的 2 个分片转移到第二台MySQL上, 并完成记录要求,最快的数据迁移做法,中断业务时间最短 2.针对分片以及迁 ...
随机推荐
- Hadoop本地编写的jar包放到集群执行时报错处理
错误描述: 020-03-24 22:45:23,204 WARN org.apache.hadoop.yarn.server.nodemanager.DefaultContainerExecutor ...
- java JDK的安装和环境配置(windows10)
1.下载JDK,安装.http://www.oracle.com/technetwork/java/javase/archive-139210.html 下载地址 2.配置JDK. (右键我的电脑 ...
- QT 如何让release生成的EXE可在他人电脑上运行(尝试了全网的方法后,这应该能帮你解决)
这两天,迅速上手了QT并用其基于C++编写了一个含UI的小程序 跳过中间的开发阶段 当我兴致满满的要将程序打包时,却是费尽周折,搜尽全网的关于QT的打包教程,最后都不顶用. 后面自己和队友的共同发现, ...
- drf视图类总结

- [已解决] npm ERR! code EINVALIDPACKAGENAME Invalid package name "": name cannot start with an underscore;
打开 cmd 输入 `npm update -g` 等待更新完成即可
- Python 每日提醒写博客小程序,使用pywin32、bs4库
死循环延迟调用方法,使用bs4库检索博客首页文章的日期是否与今天日期匹配,不匹配则说明今天没写文章,调用pywin32库进行弹窗提醒我写博客.
- Java学习day42
继续刷力扣题
- 不借助 Javascript,利用 SVG 快速构建马赛克效果
之前在公众号转发了好友 Vajoy 的一篇文章 -- 巧用 CSS 把图片马赛克风格化. 核心是利用了 CSS 中一个很有意思的属性 -- image-rendering,它可以用于设置图像缩放算法. ...
- Selenium3自动化测试【27】Frame的操作
本篇文章内容摘要 " 讲解Python3+Selenium3如何处理Frame窗体" 同步视频知识与系列知识内容,可关注:[公众号]:柒哥测试:[WX]:Lee-890;[视频号] ...
- Java语言学习day27--8月02日
今日内容介绍1.Eclipse常用快捷键操作2.Eclipse文档注释导出帮助文档3.Eclipse项目的jar包导出与使用jar包4.不同修饰符混合使用细节5.辨析何时定义变量为成员变量6.类.抽象 ...