mycat介绍
Mycat 背后是阿里曾经开源的知名产品——Cobar。Cobar 的核心功能和优势是 MySQL 数据库分片,此产品曾经广为流传,据说最早的发起者对 Mysql 很精通,后来从阿里跳槽了,阿里随后开源的 Cobar,并维持到 2013 年年初,然后,就没有然后了。
Cobar 的思路和实现路径的确不错。基于 Java 开发的,实现了 MySQL 公开的二进制传输协议,巧妙地将自己伪装成一个 MySQL Server,目前市面上绝大多数 MySQL 客户端工具和应用都能兼容。比自己实现一个新的数据库协议要明智的多,因为生态环境在哪里摆着。
Mycat 是基于 cobar 演变而来,对 cobar 的代码进行了彻底的重构,使用 NIO 重构了网络模块,并且优化了 Buffer 内核,增强了聚合,Join 等基本特性,同时兼容绝大多数数据库成为通用的数据库中间件。
简单的说,MyCAT就是:
一个新颖的数据库中间件产品支持mysql集群,或者mariadb cluster,提供高可用性数据分片集群。你可以像使用mysql一样使用mycat。对于开发人员来说根本感觉不到mycat的存在。
二,环境部署
准备了三台linux虚拟机 ip分别是192.168.25.128,192.168.25.129,192.168.25.130
一台项目发布机器 ip为192.168.25.5
Jdk版本 1.7.0_71
Mysql版本号5.5.49
Mycat版本1.4
部署结构
访问流程
Mycat部署测试
进入/mycat/bin 目录下
输入命令./mycat start
查看进程是否启动 ps -ef|grep mycat
进程启动后cd..
进入日志目录cd logs
查看wrapper日志 tail wrapper.log
当出现suuccessfully 信息之后表示可以正常启动
三,mycat基本配置流程
进入mycat\conf目录
使用notepad++远程打开文件查看 并修改schema.xml 这里演示mycat常用的三种规则 (1)以id 范围分表id为自增数字 (2)以string类型字段 hash分表 (3) 以时间分表
首先双击打开schema.xml
<schema name="MyCatDB" checkSQLschema="false" sqlMaxLimit="100">
<p style="margin-left:0cm;"> <!-- auto sharding by id (long) --></p>
<p style="margin-left:0cm;"> <table name="t_order" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" /></p>
<p style="margin-left:0cm;"><table name="t_order_time" primaryKey="ID" dataNode="dn1,dn2,dn3" rule="sharding-by-date-tr04"/></p>
<p style="margin-left:0cm;"> <table name="t_order_hash" primaryKey="ID" dataNode="dn1,dn2,dn3" rule="sharding-by-murmur"/></p>
<p style="margin-left:0cm;"></schema></p>
</td>
</tr></tbody></table></div><p style="margin-left:0cm;"> </p>
配置每个昵称库与实际库名的关系
<dataNode name="dn1" dataHost="localhost1" database="db128" />
<p style="margin-left:0cm;"> <dataNode name="dn2" dataHost="localhost2" database="db129" /></p>
<p style="margin-left:0cm;"> <dataNode name="dn3" dataHost="localhost3" database="db130" /></p>
</td>
</tr></tbody></table></div><p style="margin-left:0cm;"> </p>
配置每个库的实际ip地址和连接配置
<p style="margin-left:0cm;"><dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"</p>
<p style="margin-left:0cm;"> writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"></p>
<p style="margin-left:0cm;"> <heartbeat>select user()</heartbeat></p>
<p style="margin-left:0cm;"> <writeHost host="hostM1" url="192.168.25.128:3306" user="root"</p>
<p style="margin-left:0cm;"> password="root"></p>
<p style="margin-left:0cm;"> <!-- <readHost host="hostS1" url="192.168.25.129:3306" user="root"</p>
<p style="margin-left:0cm;"> password="root" /></p>
<p style="margin-left:0cm;"> <readHost host="hostS2" url="192.168.25.130:3306" user="root"</p>
<p style="margin-left:0cm;"> password="root" /> --></p>
<p style="margin-left:0cm;"> </writeHost></p>
<p style="margin-left:0cm;"> </dataHost></p>
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;"> <dataHost name="localhost2" maxCon="1000" minCon="10" balance="0"</p>
<p style="margin-left:0cm;"> writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"></p>
<p style="margin-left:0cm;"> <heartbeat>select user()</heartbeat></p>
<p style="margin-left:0cm;"> <writeHost host="hostM2" url="192.168.25.129:3306" user="root"</p>
<p style="margin-left:0cm;"> password="root"></p>
<p style="margin-left:0cm;"> </writeHost></p>
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;"> </dataHost></p>
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;"> <dataHost name="localhost3" maxCon="1000" minCon="10" balance="0"</p>
<p style="margin-left:0cm;"> writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"></p>
<p style="margin-left:0cm;"> <heartbeat>select user()</heartbeat></p>
<p style="margin-left:0cm;"> <writeHost host="hostM3" url="192.168.25.130:3306" user="root"</p>
<p style="margin-left:0cm;"> password="root"></p>
<p style="margin-left:0cm;"> </writeHost></p>
<p style="margin-left:0cm;"> </dataHost></p>
</td>
</tr></tbody></table></div><p style="margin-left:0cm;"> </p>
配置路由
打开相同路径下router.xml文件
<queryRouter schema="MyCatDB">
<p style="margin-left:0cm;"> <dataNode></p>
<p style="margin-left:0cm;"> <name>db128</name></p>
<p style="margin-left:0cm;"> <queryNode>db128</queryNode></p>
<p style="margin-left:0cm;"> </dataNode></p>
<p style="margin-left:0cm;"> <dataNode></p>
<p style="margin-left:0cm;"> <name>db129</name></p>
<p style="margin-left:0cm;"> <queryNode>db129</queryNode></p>
<p style="margin-left:0cm;"> </dataNode></p>
<p style="margin-left:0cm;"> <dataNode></p>
<p style="margin-left:0cm;"> <name>db130</name></p>
<p style="margin-left:0cm;"> <queryNode>db130</queryNode></p>
<p style="margin-left:0cm;"> </dataNode></p>
<p style="margin-left:0cm;"> </queryRouter></p>
</td>
</tr></tbody></table></div><p style="margin-left:0cm;"> </p>
配置规则
打开同路径下rule.xml
<tableRule name="auto-sharding-long">
<p style="margin-left:0cm;"> <rule></p>
<p style="margin-left:0cm;"> <columns>id</columns></p>
<p style="margin-left:0cm;"> <algorithm>rang-long</algorithm></p>
<p style="margin-left:0cm;"> </rule></p>
<p style="margin-left:0cm;"> </tableRule></p>
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;"> <tableRule name="sharding-by-murmur"></p>
<p style="margin-left:0cm;"> <rule></p>
<p style="margin-left:0cm;"> <columns>id</columns></p>
<p style="margin-left:0cm;"> <algorithm>murmur</algorithm></p>
<p style="margin-left:0cm;"> </rule></p>
<p style="margin-left:0cm;"> </tableRule></p>
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;"> <tableRule name="sharding-by-date-tr04"></p>
<p style="margin-left:0cm;"> <rule></p>
<p style="margin-left:0cm;"> <columns>CREATE_TIME</columns></p>
<p style="margin-left:0cm;"> <algorithm>sharding-by-date</algorithm></p>
<p style="margin-left:0cm;"> </rule></p>
<p style="margin-left:0cm;"> </tableRule></p>
</td>
</tr></tbody></table></div><p style="margin-left:0cm;"> </p>
配置规则引入方法
<!—以Id范围分表-- >
<p style="margin-left:0cm;"><function name="rang-long"</p>
<p style="margin-left:0cm;"> class="org.opencloudb.route.function.AutoPartitionByLong"></p>
<p style="margin-left:0cm;"> <property name="mapFile">autopartition-long.txt</property> <!--设置Id范围的文件-- ></p>
<p style="margin-left:0cm;"> </function></p>
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;"><function name="murmur"</p>
<p style="margin-left:0cm;"> class="org.opencloudb.route.function.PartitionByMurmurHash"></p>
<p style="margin-left:0cm;"> <property name="seed">0</property><!-- 默认是0 --></p>
<p style="margin-left:0cm;"> <property name="count">3</property><!-- 要分片的数据库节点数量,必须指定,否则没法分片 --></p>
<p style="margin-left:0cm;"> <property name="virtualBucketTimes">160</property><!-- 一个实际的数据库节点被映射为这么多虚拟节点,默认是160倍,也就是虚拟节点数是物理节点数的160倍 --></p>
<p style="margin-left:0cm;"> <!-- <property name="weightMapFile">weightMapFile</property> 节点的权重,没有指定权重的节点默认是1。以properties文件的格式填写,以从0开始到count-1的整数值也就是节点索引为key,以节点权重值为值。所有权重值必须是正整数,否则以1代替 --></p>
<p style="margin-left:0cm;"> <!-- <property name="bucketMapPath">/etc/mycat/bucketMapPath</property></p>
<p style="margin-left:0cm;"> 用于测试时观察各物理节点与虚拟节点的分布情况,如果指定了这个属性,会把虚拟节点的murmur hash值与物理节点的映射按行输出到这个文件,没有默认值,如果不指定,就不会输出任何东西 --></p>
<p style="margin-left:0cm;"> </function></p>
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;"><function name="sharding-by-date" class="org.opencloudb.route.function.PartitionByDate"></p>
<p style="margin-left:0cm;"> <property name="dateFormat">yyyy-MM-dd</property> <! --日期格式-- ></p>
<p style="margin-left:0cm;"> <property name="sBeginDate">2018-09-13</property> <!-- 起始日期 -- ></p>
<p style="margin-left:0cm;"> <property name="sPartionDay">10</property> <!—分表间隔à</p>
<p style="margin-left:0cm;"> </function> </p>
<p style="margin-left:0cm;"> </p>
</td>
</tr></tbody></table></div><p style="margin-left:0cm;">如果是要引入外部配置文件的规则需要新建文件</p>
打开autopartition-long.txt文件
配置server.xml
四,mycat数据测试
首先通过客户端工具分别连接三个物理库和逻辑库
我们先测试创建表的时候能否同步到三个物理库中
双击MyCatDB库执行SQL
DROP TABLE IF EXISTS `t_order`;
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;">CREATE TABLE `t_order` (</p>
<p style="margin-left:0cm;"> `id` bigint(20) NOT NULL AUTO_INCREMENT,</p>
<p style="margin-left:0cm;"> `name` varchar(20) DEFAULT NULL,</p>
<p style="margin-left:0cm;"> PRIMARY KEY (`id`)</p>
<p style="margin-left:0cm;">) ENGINE=InnoDB DEFAULT CHARSET=utf8;</p>
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;">/*Table structure for table `t_order_hash` */</p>
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;">DROP TABLE IF EXISTS `t_order_hash`;</p>
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;">CREATE TABLE `t_order_hash` (</p>
<p style="margin-left:0cm;"> `id` varchar(20) NOT NULL,</p>
<p style="margin-left:0cm;"> `name` varchar(20) DEFAULT NULL,</p>
<p style="margin-left:0cm;"> PRIMARY KEY (`id`)</p>
<p style="margin-left:0cm;">) ENGINE=InnoDB DEFAULT CHARSET=utf8;</p>
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;">/*Table structure for table `t_order_time` */</p>
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;">DROP TABLE IF EXISTS `t_order_time`;</p>
<p style="margin-left:0cm;"> </p>
<p style="margin-left:0cm;">CREATE TABLE `t_order_time` (</p>
<p style="margin-left:0cm;"> `id` bigint(20) NOT NULL AUTO_INCREMENT,</p>
<p style="margin-left:0cm;"> `create_time` datetime DEFAULT NULL,</p>
<p style="margin-left:0cm;"> PRIMARY KEY (`id`)</p>
<p style="margin-left:0cm;">) ENGINE=InnoDB DEFAULT CHARSET=utf8;</p>
</td>
</tr></tbody></table></div><p style="margin-left:0cm;"> </p>
此时我们会发现MyCatDB逻辑库中多了三个表
此时我们分别去查看其他三个物理库的表是否同步创建
测试id 范围分表规则
准备数据
insert into `t_order`(`id`,`name`) values (1,'测试一'),(5000000,'测试二'),( 10000001,'测试三');
根据上面id 范围的配置规则 id 在0-5000000之间 存放在索引为0位置的库也就是db128,5000000-10000000 存放在db129 10000001 存放于db130中
运行SQL
结果如下
MyCatDB逻辑库数据
2. 其他三个库的结果
由结果可见该规则会根据Id在rule的配置文件中的范围进行分表
此地方需要注意点:当id超过所设置的范围后MYCAT会抛异常
测试hash规则
准备数据
insert into `t_order_hash`(`id`,`name`) values ('HASH1111111',' 哈希测试一'),('HASH2222222','哈希测试二'),('HASH3333333','哈希测试三'),('HASH44444444','哈希测试四'),('HASH55555555','哈希测试五'),('HASH6666666','哈希测试六');
根据hash规则 数据会以varchar类型的id 以hash值分布在三个库中
运行结果:
再查看其他三个库的结果
为了检验结果是否随机分布还是以hash值分布 我们删除数据重新执行了一遍
发现结果一致
测试日期规则
准备数据
<p style="margin-left:0cm;"><span style="color:#000000;">insert into `t_order_time`(`id`,`create_time`) values (1,'2018-09-20 00:00:00'),(2,'2018-09-24 00:00:00'),(3,'2018-10-01 00:00:00'),(4,'2018-10-03 00:00:00');</span></p>
</td>
</tr></tbody></table></div><p style="margin-left:0cm;"><span style="color:#000000;">预期结果 根据我们预设的初始日期2018-09-13日开始每隔10天将数据依次分片到后面的库</span></p>
运行结果:
由结果可见:
2018-09-20 在索引为0的库 2018-09-24 以及2018-10-01 分在索引为1的库
2018-10-03 分放到索引为3的库结果符合预期分片正常
Mycat 其他规则
参考网站 https://blog.csdn.net/yifanSJ/article/details/79736050
Mycat接入工程
spring.datasource.druid.driver-class-name = com.mysql.jdbc.Driver spring.datasource.druid.url = jdbc:mysql://192.168.25.128:8066/MyCatDB?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false spring.datasource.druid.username = mycat spring.datasource.druid.password = mycat
<p style="margin-left:0cm;"> </p>
</td>
</tr></tbody></table></div><p style="margin-left:0cm;"> </p>
mycat日志查看
cd /mycat/logs
wrapper.log 查看mycat启动日志
mycat.log查看mycat运行日志
如果mysql与mycat版本不匹配会出现错误
com.mysql.jdbc.PacketTooBigException: Packet for query is too large (44 > -1). You can change this value on the server by setting the max_allowed_packet’ variable 。
解决办法
检查 mysqljdbc 驱动的版本,在使用 mycat1.3 和 mycat1.4 版本情况下,不要使用 jdbc5.1.37 和 38 版本的驱动,会出现如下异常报错: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (60 > -1). You can change this value on the server by setting the max_allowed_packet’ variable 。建议使用 jdbc5.1.35 或者 36 的版本。 mycat1.6 同样会出现这个问题,换成 mysql5.1.40 同样可用
Mycat 所有对表操作的语句表名必须全大写
对MyCat操作的表必须在schema.xml中有定义
无法使用selct ….from dual 因为dual没有定义
无法使用select * from table 需要明确字段名
无法给全大写字段类似STATUS 取别称为status
使用id范围分片的时候插入的时候id必须有值mycat无法实现自增涨
定义了库的片数之后如果值超过所有库的存放范围会报异常
低版本mycat无法给datetime字段设置默认值current timestrap
插入语句不要连带库名要不然会插入存在的指定库中
其他注意点查看地址:
https://blog.csdn.net/n447194252/article/details/75304303/