# 配置 MyCat
本章讲解如何在我们搭建好的两个集群分片上,如何配置到 Mycat 中,另外配置两个库用来练习。
# 高可用 MyCat
一个 MyCat 就够用了,另外一个用来做高可用,当一个挂掉之后,另一个可以接上工作。
# MyCat 部署方案
虚拟机 | IP 地址 | 端口 | 容器 | 数据卷 |
---|---|---|---|---|
docker-1 | 192.168.56.105 | 8066/9066 | mycat1 | mycat1 |
docker-2 | 192.168.56.107 | 8066/9066 | mycat2 | mycat2 |
# MyCat 主要配置文件
server.xml
配置虚拟账户、虚拟逻辑库、主键生成方式
schema.xml
数据库连接、数据表使用什么路由规则
rule.xml
可自己定制数据切分规则
# MyCat 到底是什么?
MyCat 是 MySQL 数据库中间件产品,运行的时候会把自己虚拟成 MySQL 数据库,包括虚拟的逻辑库和数据表。
- 虚拟逻辑库
- 虚拟数据表
- 虚拟账户
# 配置虚拟账户
seerver.xml 中配置虚拟账户
<mycat:server>
<user name="admin">
<property name="password">123456</property>
<property name="schemas">neti</property>
</user>
</mycat:server>
2
3
4
5
6
- schemas:该虚拟账户能访问的虚拟数据库
# 什么是读写分离
数据库中间件把读写任务分别发送给不同节点执行,可以降低单一节点负载;
对于 PXC 集群来说,不需要设置读写分离,值做均衡负载即可。(因为 PXC 集群每一个节点都是相同地位)
对于 Replication 集群主从节点功能明确,需要做读写分离。写发送到 master,读发送到 Slave
# 配置 PXC 负载均衡
修改 seerver.xml 文件,加入 PXC 负载均衡内容
<dataHost name="pxc1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="p1w1" url="192.168.56.105:9001" user="root"
password="123456">
</writeHost>
<writeHost host="p1w2" url="192.168.56.107:9001" user="root"
password="123456" />
<writeHost host="p1w3" url="192.168.56.108:9001" user="root"
password="123456" />
</dataHost>
2
3
4
5
6
7
8
9
10
11
balance: 0:不使用读写分离,所有读写请求都放给写节点
writeType:1:随机发送读写请求给节点;如果已宕机,就不会发该宕机的了
switchType:1:根据自身心跳结果,判断哪个节点宕机了
slaveThreshold:Replication 集群有关系
当从库与主库的时间相差 100 秒,就会把该节点踢掉,不会从该从节点中读取数据
heartbeat:心跳语句
writeHost:写节点链接真实数据库配置
host:给该节点的一个别名
笔者这里有三个节点,都定义下来
下面是本此 PXC 集群配置的文件内容
<!-- pxc1 集群--->
<dataHost name="pxc1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="p1w1" url="192.168.56.105:9001" user="root"
password="123456">
</writeHost>
<writeHost host="p1w2" url="192.168.56.107:9001" user="root"
password="123456" />
<writeHost host="p1w3" url="192.168.56.108:9001" user="root"
password="123456" />
</dataHost>
<!-- pxc2 集群--->
<dataHost name="pxc2" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="p2w1" url="192.168.56.105:9002" user="root"
password="123456">
</writeHost>
<writeHost host="p2w2" url="192.168.56.107:9002" user="root"
password="123456" />
<writeHost host="p2w3" url="192.168.56.108:9002" user="root"
password="123456" />
</dataHost>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 配置 Replication 集群读写分离
确认我们的 Replication 方案:Replication 镜像不能配置双向主从同步,所以只能使用一写三读
上图是两个方案:
一主多从:
缺点就是,当主节点挂掉之后,就无法写入数据了
多主多从:
让两个主节点互为主从同步,A 主节点,下挂 B 从节点,但是 B 主节点设置为主节点,也就是它们互相作为从。
使用读写分离时,当写节点宕机后,MyCat 就不会使用它对应的读节点了,因为数据不同步了。
对于多住多从的配置,需要我们自己去封装容器,这个也是比较复杂的。所以本节就做一主多从。后续章节再来讲解
<dataHost name="rep1" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="p1w1" url="192.168.56.105:9003" user="root" password="123456">
<readHost host=”r1r1“ url="192.168.56.107:9003" user="root" password="123456"/>
...
</writeHost>
</dataHost>
2
3
4
5
6
7
8
- balance :3 ,启用读写分离功能
本次 Replication 集群配置
<!-- rep1 集群--->
<dataHost name="rep1" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="p1w1" url="192.168.56.105:9003" user="root" password="123456">
<readHost host="r1r1" url="192.168.56.107:9003" user="root" password="123456"/>
<readHost host="r1r2" url="192.168.56.108:9003" user="root" password="123456"/>
</writeHost>
</dataHost>
<!-- rep2 集群--->
<dataHost name="rep2" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="r2w1" url="192.168.56.105:9004" user="root" password="123456">
<readHost host="r2r1" url="192.168.56.107:9004" user="root" password="123456"/>
<readHost host="r2r2" url="192.168.56.108:9004" user="root" password="123456"/>
</writeHost>
</dataHost>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
具体的各个配置含义,去查阅 MyCat 的官方手册。
# 逻辑库配置
我们对虚拟表的读写都会路由到真实的物理表上面去。所以配置 dataHost 使用真实数据库上的哪些库
<dataNode>
标签可以设置使用的真实逻辑库
<dataNode name="dn1" dataHost="pxc1" database="neti"></dataNode>
- name:dataNode 的名称
- dataHost:指向的是我们刚刚配置的集群名称
- database:使用哪一个逻辑库,这个是对应真实数据库中的库名
本次配置内容
<!-- 新零售数据库的集群与逻辑库映射 -->
<dataNode name="dn1" dataHost="pxc1" database="neti"></dataNode>
<dataNode name="dn2" dataHost="pxc2" database="neti"></dataNode>
<dataNode name="dn3" dataHost="rep1" database="neti"></dataNode>
<dataNode name="dn4" dataHost="rep2" database="neti"></dataNode>
<!-- 集群与练习库的映射;先拿练习库来练手 -->
<dataNode name="tdn1" dataHost="pxc1" database="t1"></dataNode>
<dataNode name="tdn2" dataHost="pxc2" database="t1"></dataNode>
<dataNode name="tdn3" dataHost="rep1" database="t2"></dataNode>
<dataNode name="tdn4" dataHost="rep2" database="t2"></dataNode>
2
3
4
5
6
7
8
9
10
11
练习库使用了两个不同的逻辑库,这个叫做库的垂直切分;
需要在我们集群数据库上创建上面对应的 neti 和 t1 、t2 数据库
# 配置虚拟库和虚拟表
因为 MyCat 并不存储数据,所以必须要配置可以使用的虚拟逻辑库和关系表。
<schema>
标签可以设置虚拟逻辑库
<table>
标签可以设置虚拟关系表
<schema name="t2" checkSQLschema="false" sqlMaxLimit="100">
<table name="teacher" type="global" dataNode="tdn3,tdn4"></table>
<table name="student" rule="mod-long" dataNode="tdn3,tdn4"></table>
</schema>
2
3
4
schema 属性:
checkSQLschema:是否去掉逻辑库名
如
select t2.student
,如果为 true,则会去掉 t2 变成select student
去真实数据库上执行sqlMaxLimit:每条查询语句最多返回多少条数据
table 属性:
name:虚拟表名字,这个表对应真实库中的表名
type:
global:不做水平切分的表;所有节点上都有全部的表数据
这里老师的数据比较少,就不用切分了
dataNode:对应的真实逻辑库
rule: 分配规则
mod-long
:按照主键值求模切分这里用了两个 Replication 集群,如果有 1000 个学生,那么每个集群上会保存 500 条数据
本次配置的内容
<!-- t2 库配置 -->
<schema name="t2" checkSQLschema="false" sqlMaxLimit="100">
<table name="teacher" type="global" dataNode="tdn3,tdn4"></table>
<table name="student" rule="mod-long" dataNode="tdn3,tdn4"></table>
</schema>
<!-- t1 库配置,表也暂时不配置 -->
<schema name="t1" checkSQLschema="false" sqlMaxLimit="100">
</schema>
<!-- 新零售库配置,表暂时不配置 -->
<schema name="neti" checkSQLschema="false" sqlMaxLimit="100">
</schema>
2
3
4
5
6
7
8
9
10
11
对于 schema.xml 中的虚拟账户可使用的逻辑库就需要加上 t1 和 t2 了
<user name="admin">
<property name="password">123456</property>
<property name="schemas">neti,t1,t2</property>
</user>
2
3
4
# 修改 mod-long 算法
MyCat 默认的 mod-long 是按照三个分配切分数据,我们这里需要修改下这个默认值;
我们这里 t2 库对应的只有两个节点,所以需要修改为 2
在 rule.xml 中修改
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">2</property>
</function>
2
3
4
# 本章最终配置一览
# server.xml
其他的配置是很多默认的配置,没有动他们;改动的就是删除了其他的 user 标签,只留下了一个 user 配置
<user name="admin">
<property name="password">123456</property>
<property name="schemas">neti,t1,t2</property>
</user>
2
3
4
# schema.xml
配置文件中标签的顺序也需要注意下,否则会在启动的时候报错
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- t2 库配置 -->
<schema name="t2" checkSQLschema="false" sqlMaxLimit="100">
<table name="teacher" type="global" dataNode="tdn3,tdn4"></table>
<table name="student" rule="mod-long" dataNode="tdn3,tdn4"></table>
</schema>
<!-- t1 库配置,表也暂时不配置 -->
<schema name="t1" checkSQLschema="false" sqlMaxLimit="100">
</schema>
<!-- 新零售库配置,表暂时不配置 -->
<schema name="neti" checkSQLschema="false" sqlMaxLimit="100">
</schema>
<!-- 新零售数据库的集群与逻辑库映射 -->
<dataNode name="dn1" dataHost="pxc1" database="neti"></dataNode>
<dataNode name="dn2" dataHost="pxc2" database="neti"></dataNode>
<dataNode name="dn3" dataHost="rep1" database="neti"></dataNode>
<dataNode name="dn4" dataHost="rep2" database="neti"></dataNode>
<!-- 集群与练习库的映射;先拿练习库来练手 -->
<dataNode name="tdn1" dataHost="pxc1" database="t1"></dataNode>
<dataNode name="tdn2" dataHost="pxc2" database="t1"></dataNode>
<dataNode name="tdn3" dataHost="rep1" database="t2"></dataNode>
<dataNode name="tdn4" dataHost="rep2" database="t2"></dataNode>
<!-- pxc1 集群-->
<dataHost name="pxc1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="p1w1" url="192.168.56.105:9001" user="root" password="123456" />
<writeHost host="p1w2" url="192.168.56.107:9001" user="root" password="123456" />
<writeHost host="p1w3" url="192.168.56.108:9001" user="root" password="123456" />
</dataHost>
<!-- pxc2 集群-->
<dataHost name="pxc2" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="p2w1" url="192.168.56.105:9002" user="root" password="123456" />
<writeHost host="p2w2" url="192.168.56.107:9002" user="root" password="123456" />
<writeHost host="p2w3" url="192.168.56.108:9002" user="root" password="123456" />
</dataHost>
<!-- rep1 集群-->
<dataHost name="rep1" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="p1w1" url="192.168.56.105:9003" user="root" password="123456">
<readHost host="r1r1" url="192.168.56.107:9003" user="root" password="123456"/>
<readHost host="r1r2" url="192.168.56.108:9003" user="root" password="123456"/>
</writeHost>
</dataHost>
<!-- rep2 集群-->
<dataHost name="rep2" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="r2w1" url="192.168.56.105:9004" user="root" password="123456">
<readHost host="r2r1" url="192.168.56.107:9004" user="root" password="123456"/>
<readHost host="r2r2" url="192.168.56.108:9004" user="root" password="123456"/>
</writeHost>
</dataHost>
</mycat:schema>
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
这里总结下里面的配置关系:
dataHost:配置一个物理集群信息;包括该物理集群中哪些节点是写、哪些节点是读节点
dataNode:配置的是 物理集群中 对应的 物理库;
由于一个物理库中的名称是唯一的,但是可以有多张表,后面再映射该库中有哪些表的时候,就会多次用到,该标签抽象出来,被重复使用。
schema:配置虚拟逻辑库信息
table:配置是物理库中的表
包括表中的数据要以什么规则切分?这些表存储在哪个物理库上中?
###rule.xml
该表中默认配置了很多规则,由于我们目前只用到了一个,其他的都可以删除掉
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">
<tableRule name="mod-long">
<rule>
<columns>id</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">2</property>
</function>
</mycat:rule>
2
3
4
5
6
7
8
9
10
11
12
13
14