Mycat 笔记 1 中如何实现高效的读写分离策略?
- 内容介绍
- 文章标签
- 相关推荐
本文共计3507个文字,预计阅读时间需要15分钟。
2022-05-03 参考链接:https://www.jianshu.com/p/460ab9c072be
1.目的:验证Mycat的读写分离
环境:192.168.0.100(master)、192.168.0.101(slave1)、192.168.0.102(slave2)、192.168.0.170(Mycat)Mycat需要配置主从数据库。2022-05-03
参考:www.jianshu.com/p/460ab9c072be
目的:验证 mycat 的读写分离
环境:
192.168.0.100 master
192.168.0.101 slave1
192.168.0.102 slave2
192.168.0.170 mycat
需要将主从的 world 数据配置成 mycat 的逻辑数据库,以便后续进行分库分表,
通过 mycat 节点(170)来访问主从,
写操作在主库(100)上,读操作由从库(101 和 102)负担
100 节点和 101、102 节点的主从环境搭建过程(略)
3. mycat 安装170 节点安装 mycat
3.1 jdkmycat 是 java 写的,所以需要先确定有 java 开发环境
yum install java
虽然已经有 mycat2,但此处采用的版本是 1.6
解压
bin目录 可以执行文件
conf 目录 配置文件
log 目录 日志
mycat 的一些配置信息
主要用来配置 mycat 的系统参数
<system>
...
<property name="serverPort">8066</property>
<property name="managerPort">9066</property
...
</system>
如上:
这两个就分别定义了 mycat 的数据端口(8066)和管理端口(9066)
如果后续连接到 mycat 的话,就是通过这两个端口
配置访问 mycat 的用户和权限,
后续访问 mycat 的时候,就是使用下面定义的账号和密码来登录
(在这个例子中,需要配置一个用来登录 mycat 的账号)
<user name="mycat">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>
<property name="readOnly">true</property>
<property name="defaultSchema">TESTDB</property>
</user>
如上,
如果需要多个用户的话,就写多个 <user> 标签
行 1:
name="xxx" 就是定义用来访问 mycat 的账号,
可能还会有这样的字段 <user name="mycat" default="true">,default 字段表示这个账号是默认账号。
行 2:
属性 password 的值 123456 就是这个账号的密码,
行 3:
属性 schemas 表示允许该用户访问的逻辑库,
可以有多个,使用逗号分隔,在 schema.xml 中配置
mycat 在分布式中,其实一个表的数据可能在不同的数据库节点中,但是对外的话,需要表现在同一个数据库下的同一个表里面面,这个就是逻辑库和逻辑表。
行 4:
属性 readOnly,如名字描述,限定只读,设置后账号就没法进行写操作
4.1.2.1 <user> 标签下的 <privileges> 标签
(此例中配置的账号,无需这部分)
有的时候需要限制用户对某些表的访问权限,就是在 <privileges> 标签进行定义
<user name="mycat">
...
<!-- 表级 DML 权限设置 -->
<!--
<privileges check="false">
<schema name="TESTDB" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table>
</schema>
</privileges>
-->
</user>
check 的值 true / false 表明是否开启
dml 的值是四位二进制,分别表示 insert,update,select,delete 这四种权限。
如果 table 标签里面没有配置 dml 权限位的话,就会从 schema 标签继承
如上表示 mycat 这个用户拥有 tb02 这个表的四种权限,在 tb01 这个表上,没有这四种权限。
用于配置逻辑库、逻辑表相关信息
当应用连接到 mycat 的时候,通过 server.xml 认证后,看到的逻辑库就是在 schema.xml 中定义的
4.2.1 <schema> 标签
定义逻辑库
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100"
randomDataNode="dn1" dataNode="dn1">
...
</schema>
name:
定义逻辑库名,唯一(和前面 server.xml 中相对应)
checkSQLschema:
检查发给 mycat 的 sql 是否包含库名,true 会将 库名删除掉,如:
select * from world.city 会被 mycat 修改为 select * from city;
在写语句的时候,可以在语句前写一个 use TESTDB; select * from talbe;
sqlMaxLimit:
限制返回结果集的行数,-1 表示关闭
如果收到的 sql 语句没有 limit,那么 mycat 会自动添加上(没有分库的前提下)
dataNode
dataNode="dn1",表示默认的数据节点是 dn1,dn1 在下面的 <dataNode> 和 <dataHost> 标签继续定义
需要拆分的表在这个标签中定义
(此例中配置的账号,无需这部分,可以删除)
<schema ...>
<table name="customer" primaryKey="id" dataNode="dn1,dn2"
rule="sharding-by-intfile" autoIncrement="true"
fetchStoreNodeByJdbc="true">
</table>
</schema>
name:
定义逻辑表名,对应着数据库中真实的表名,多个表的话,使用逗号分隔,表明多个表使用这个配置。
primaryKey:
逻辑表的主键,对应着数据库真实表的主键,
dataNode:
真实表所在的数据节点,
rule:
分片的规则,对应 rule.xml 下的 tableRule 标签的 name 属性,
定义数据节点, 将来的分库就是分到这些节点中.
我的理解,1 个数据节点对应着一组主从
<schema> 标签中的 dataNode,就是在这里指定具体的信息,
dataHost:
内容会在 <dataHost> 标签继续定义具体的 ip 这些信息
database:
指向存储逻辑表的物理数据库,也就是 <schema name="TESTDB"> 标签里面的 TESTDB 这个逻辑库对应的物理数据库
(此例中,mycat 对应着一主两从,因此只需要一个 data node)
<dataNode name="dn1" dataHost="centos7" database="word" />
如上,我的配置中,这个一主两从的“节点”名字为 dn1,对应的主机取名为 centos7,对应的真实数据库是 word 库
4.3.4 <dataHost> 标签配置一组集群的,物理数据库主机信息
(此例中,需要将一主两从的信息写在这里)
<dataHost name="centos7" maxCon="1000" minCon="10"
balance="1" balanceType="1" writeType="0" dbType="mysql"
dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.0.100:3306"
user="root" password="123456">
<readHost host="hostS1" url="192.168.0.101:3306" password="123456" user="root" weight="1"></readHost>
<readHost host="hostS2" url="192.168.0.102:3306" password="123456" user="root" weight="1"></readHost>
</writeHost>
</dataHost>
name:
定义主机名,和<dataNode> 的 dataHost 字段对应
maxCon,minCon:
连接池的最大连接数,最小(初始化连接池的大小)
dbType:
指定后端数据库的连接类型,mysql / JDBC
dbDriver:
后端数据库的连接驱动,native / JDBC
我选择 native,后面写地址的时候直接 ip:port 即可
balance:
指定读写分离
0:不开启读写分离,所有的操作都发往可用的 write host
1:所有的 read host 和预备(stand for)write host 参与 select 语句的负载均衡
2:所有的读操作都随机在 write host 和 read host 上
3:所有的读请求分发到 write host 对应的 read host(readHost 标签是 writeHost 的下级),也就是 write host 不会承担读压力
writeType:
写节点的负载均衡
0:所有写操作均由第一个 write host 承担,第一个宕机再有第二个负担
1:mycat 1.5 已经废弃,不推荐使用。所有写操作随机发送到 write host,
2:基于 mysql 主从状态决定是否切换
-1:不自动切换
switchTyep:
主从切换方式,
1:默认,自动切换
2:基于 mysql 主从同步状态决定是否切换(心跳检测为 show slave status)
3:基于 MySQL galary cluster(mariaDB 的多主高可用)的切换(show status like 'wsrep%')
slaveThreshold:
定义主从延迟,当延迟超过这个阀值,会过滤掉这个 slave,防止读取到陈旧数据
如果不为 0,还会影响 switchType=2 时候的切换,这意味着数据不是最新
<heartbeat> 标签
定义心跳检测的语句
<writeHost> 标签和 <readHost> 标签
配置写实例,write host 也就是 master 节点,当 writeHost 宕机的话,会切换到候选 writeHost;read host 也就是 slave 节点
<readHost> 标签是 <writeHost> 标签的子标签
<writeHost host="hostM1" url="192.168.0.100:3306"
user="root" password="123456">
<readHost host="hostS1" url="192.168.0.101:3306" password="123456"
user="root" weight="1"></readHost>
<readHost host="hostS2" url="192.168.0.102:3306" password="123456"
user="root" weight="1"></readHost>
</writeHost>
host:
标识不同实例名称,通常 write host 以 M1、M2、... 为后缀,read host 以 S1、S2、... 为后缀
url:
配置数据的连接地址,
如果 dbDriver=native,那么就是 address:port 的形式,
user、password:
访问主从数据库的用户名和密码
weihgt:
权重
usingDecrypt:
是否对密码加密
具体的配置如下:
server.xml
如上,配置使用 mycat 这个用户去登录 mycat,如果需要 mycat 写的话,将 readOnly 删除掉。
当然,定义的 root 用户也可以访问。
schema.xml
<mycat:schema xmlns:mycat="io.mycat/">
<schema name="TESTDB" checkSQLschema="true"
sqlMaxLimit="100" randomDataNode="dn1" dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="Centos7" database="world" />
<dataHost name="Centos7" maxCon="1000" minCon="10"
balance="1" balanceType="1" writeType="0"
dbType="mysql" dbDriver="native" switchType="1"
slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.0.100:3306"
user="root" password="123456">
<readHost host="hostS1" url="192.168.0.101:3306"
password="123456" user="root" weight="1"></readHost>
<readHost host="hostS2" url="192.168.0.102:3306"
password="123456" user="root" weight="1"></readHost>
</writeHost>
</dataHost>
</mycat:schema>
如上,mycat 的逻辑数据库 TESTDB 对应着物理数据库 world,
这个数据库需要在 master 上创建好,
在上面的配置中,定义 root 用户从 mycat 节点来访问 write host 和 read host,
因此,最好从 mycat 节点检查下,账号是否能顺利登陆。
启动前需要注意的地方:
-
主库上需要创建逻辑库对应的真实数据库
-
上面配置文件中,使用 root 用户访问 write host 和 read host,root 用户需要在允许的 host 范围内,
-
root 用户使用 mysql native password 插件
alter user root@'xxxx' identified with mysql_native_password by 'yyy'
- dbDriver 使用 native 会简单一些
启动命令
cd /usr/local/mycat/bin
./mycat console # 会将信息打印再屏幕上
# 或
./mycat start # 后台
mycat 节点为 192.168.0.170
server.xml 的时候提到过
- 9066 端口: 管理端口
- 8066 端口: 数据端口
因此,访问 192.168.0.170:8066 ,看是否能看到 mycat 的逻辑数据库 TESTDB,也就是对应的物理数据库(主从的) world
遇到的问题:
无法连接到物理库,手动连接的时候报错:
ERROR 1129 (HY000): Host '192.168.0.170' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'
到物理库上 flush hosts
如上,
能在逻辑库中查看到 city 表的数据
测试读写分离:
如上,
前两条分布在从节点上执行,(并非轮询)
最后一条以事务提交的 sql 在 master 上执行。
本文共计3507个文字,预计阅读时间需要15分钟。
2022-05-03 参考链接:https://www.jianshu.com/p/460ab9c072be
1.目的:验证Mycat的读写分离
环境:192.168.0.100(master)、192.168.0.101(slave1)、192.168.0.102(slave2)、192.168.0.170(Mycat)Mycat需要配置主从数据库。2022-05-03
参考:www.jianshu.com/p/460ab9c072be
目的:验证 mycat 的读写分离
环境:
192.168.0.100 master
192.168.0.101 slave1
192.168.0.102 slave2
192.168.0.170 mycat
需要将主从的 world 数据配置成 mycat 的逻辑数据库,以便后续进行分库分表,
通过 mycat 节点(170)来访问主从,
写操作在主库(100)上,读操作由从库(101 和 102)负担
100 节点和 101、102 节点的主从环境搭建过程(略)
3. mycat 安装170 节点安装 mycat
3.1 jdkmycat 是 java 写的,所以需要先确定有 java 开发环境
yum install java
虽然已经有 mycat2,但此处采用的版本是 1.6
解压
bin目录 可以执行文件
conf 目录 配置文件
log 目录 日志
mycat 的一些配置信息
主要用来配置 mycat 的系统参数
<system>
...
<property name="serverPort">8066</property>
<property name="managerPort">9066</property
...
</system>
如上:
这两个就分别定义了 mycat 的数据端口(8066)和管理端口(9066)
如果后续连接到 mycat 的话,就是通过这两个端口
配置访问 mycat 的用户和权限,
后续访问 mycat 的时候,就是使用下面定义的账号和密码来登录
(在这个例子中,需要配置一个用来登录 mycat 的账号)
<user name="mycat">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>
<property name="readOnly">true</property>
<property name="defaultSchema">TESTDB</property>
</user>
如上,
如果需要多个用户的话,就写多个 <user> 标签
行 1:
name="xxx" 就是定义用来访问 mycat 的账号,
可能还会有这样的字段 <user name="mycat" default="true">,default 字段表示这个账号是默认账号。
行 2:
属性 password 的值 123456 就是这个账号的密码,
行 3:
属性 schemas 表示允许该用户访问的逻辑库,
可以有多个,使用逗号分隔,在 schema.xml 中配置
mycat 在分布式中,其实一个表的数据可能在不同的数据库节点中,但是对外的话,需要表现在同一个数据库下的同一个表里面面,这个就是逻辑库和逻辑表。
行 4:
属性 readOnly,如名字描述,限定只读,设置后账号就没法进行写操作
4.1.2.1 <user> 标签下的 <privileges> 标签
(此例中配置的账号,无需这部分)
有的时候需要限制用户对某些表的访问权限,就是在 <privileges> 标签进行定义
<user name="mycat">
...
<!-- 表级 DML 权限设置 -->
<!--
<privileges check="false">
<schema name="TESTDB" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table>
</schema>
</privileges>
-->
</user>
check 的值 true / false 表明是否开启
dml 的值是四位二进制,分别表示 insert,update,select,delete 这四种权限。
如果 table 标签里面没有配置 dml 权限位的话,就会从 schema 标签继承
如上表示 mycat 这个用户拥有 tb02 这个表的四种权限,在 tb01 这个表上,没有这四种权限。
用于配置逻辑库、逻辑表相关信息
当应用连接到 mycat 的时候,通过 server.xml 认证后,看到的逻辑库就是在 schema.xml 中定义的
4.2.1 <schema> 标签
定义逻辑库
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100"
randomDataNode="dn1" dataNode="dn1">
...
</schema>
name:
定义逻辑库名,唯一(和前面 server.xml 中相对应)
checkSQLschema:
检查发给 mycat 的 sql 是否包含库名,true 会将 库名删除掉,如:
select * from world.city 会被 mycat 修改为 select * from city;
在写语句的时候,可以在语句前写一个 use TESTDB; select * from talbe;
sqlMaxLimit:
限制返回结果集的行数,-1 表示关闭
如果收到的 sql 语句没有 limit,那么 mycat 会自动添加上(没有分库的前提下)
dataNode
dataNode="dn1",表示默认的数据节点是 dn1,dn1 在下面的 <dataNode> 和 <dataHost> 标签继续定义
需要拆分的表在这个标签中定义
(此例中配置的账号,无需这部分,可以删除)
<schema ...>
<table name="customer" primaryKey="id" dataNode="dn1,dn2"
rule="sharding-by-intfile" autoIncrement="true"
fetchStoreNodeByJdbc="true">
</table>
</schema>
name:
定义逻辑表名,对应着数据库中真实的表名,多个表的话,使用逗号分隔,表明多个表使用这个配置。
primaryKey:
逻辑表的主键,对应着数据库真实表的主键,
dataNode:
真实表所在的数据节点,
rule:
分片的规则,对应 rule.xml 下的 tableRule 标签的 name 属性,
定义数据节点, 将来的分库就是分到这些节点中.
我的理解,1 个数据节点对应着一组主从
<schema> 标签中的 dataNode,就是在这里指定具体的信息,
dataHost:
内容会在 <dataHost> 标签继续定义具体的 ip 这些信息
database:
指向存储逻辑表的物理数据库,也就是 <schema name="TESTDB"> 标签里面的 TESTDB 这个逻辑库对应的物理数据库
(此例中,mycat 对应着一主两从,因此只需要一个 data node)
<dataNode name="dn1" dataHost="centos7" database="word" />
如上,我的配置中,这个一主两从的“节点”名字为 dn1,对应的主机取名为 centos7,对应的真实数据库是 word 库
4.3.4 <dataHost> 标签配置一组集群的,物理数据库主机信息
(此例中,需要将一主两从的信息写在这里)
<dataHost name="centos7" maxCon="1000" minCon="10"
balance="1" balanceType="1" writeType="0" dbType="mysql"
dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.0.100:3306"
user="root" password="123456">
<readHost host="hostS1" url="192.168.0.101:3306" password="123456" user="root" weight="1"></readHost>
<readHost host="hostS2" url="192.168.0.102:3306" password="123456" user="root" weight="1"></readHost>
</writeHost>
</dataHost>
name:
定义主机名,和<dataNode> 的 dataHost 字段对应
maxCon,minCon:
连接池的最大连接数,最小(初始化连接池的大小)
dbType:
指定后端数据库的连接类型,mysql / JDBC
dbDriver:
后端数据库的连接驱动,native / JDBC
我选择 native,后面写地址的时候直接 ip:port 即可
balance:
指定读写分离
0:不开启读写分离,所有的操作都发往可用的 write host
1:所有的 read host 和预备(stand for)write host 参与 select 语句的负载均衡
2:所有的读操作都随机在 write host 和 read host 上
3:所有的读请求分发到 write host 对应的 read host(readHost 标签是 writeHost 的下级),也就是 write host 不会承担读压力
writeType:
写节点的负载均衡
0:所有写操作均由第一个 write host 承担,第一个宕机再有第二个负担
1:mycat 1.5 已经废弃,不推荐使用。所有写操作随机发送到 write host,
2:基于 mysql 主从状态决定是否切换
-1:不自动切换
switchTyep:
主从切换方式,
1:默认,自动切换
2:基于 mysql 主从同步状态决定是否切换(心跳检测为 show slave status)
3:基于 MySQL galary cluster(mariaDB 的多主高可用)的切换(show status like 'wsrep%')
slaveThreshold:
定义主从延迟,当延迟超过这个阀值,会过滤掉这个 slave,防止读取到陈旧数据
如果不为 0,还会影响 switchType=2 时候的切换,这意味着数据不是最新
<heartbeat> 标签
定义心跳检测的语句
<writeHost> 标签和 <readHost> 标签
配置写实例,write host 也就是 master 节点,当 writeHost 宕机的话,会切换到候选 writeHost;read host 也就是 slave 节点
<readHost> 标签是 <writeHost> 标签的子标签
<writeHost host="hostM1" url="192.168.0.100:3306"
user="root" password="123456">
<readHost host="hostS1" url="192.168.0.101:3306" password="123456"
user="root" weight="1"></readHost>
<readHost host="hostS2" url="192.168.0.102:3306" password="123456"
user="root" weight="1"></readHost>
</writeHost>
host:
标识不同实例名称,通常 write host 以 M1、M2、... 为后缀,read host 以 S1、S2、... 为后缀
url:
配置数据的连接地址,
如果 dbDriver=native,那么就是 address:port 的形式,
user、password:
访问主从数据库的用户名和密码
weihgt:
权重
usingDecrypt:
是否对密码加密
具体的配置如下:
server.xml
如上,配置使用 mycat 这个用户去登录 mycat,如果需要 mycat 写的话,将 readOnly 删除掉。
当然,定义的 root 用户也可以访问。
schema.xml
<mycat:schema xmlns:mycat="io.mycat/">
<schema name="TESTDB" checkSQLschema="true"
sqlMaxLimit="100" randomDataNode="dn1" dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="Centos7" database="world" />
<dataHost name="Centos7" maxCon="1000" minCon="10"
balance="1" balanceType="1" writeType="0"
dbType="mysql" dbDriver="native" switchType="1"
slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.0.100:3306"
user="root" password="123456">
<readHost host="hostS1" url="192.168.0.101:3306"
password="123456" user="root" weight="1"></readHost>
<readHost host="hostS2" url="192.168.0.102:3306"
password="123456" user="root" weight="1"></readHost>
</writeHost>
</dataHost>
</mycat:schema>
如上,mycat 的逻辑数据库 TESTDB 对应着物理数据库 world,
这个数据库需要在 master 上创建好,
在上面的配置中,定义 root 用户从 mycat 节点来访问 write host 和 read host,
因此,最好从 mycat 节点检查下,账号是否能顺利登陆。
启动前需要注意的地方:
-
主库上需要创建逻辑库对应的真实数据库
-
上面配置文件中,使用 root 用户访问 write host 和 read host,root 用户需要在允许的 host 范围内,
-
root 用户使用 mysql native password 插件
alter user root@'xxxx' identified with mysql_native_password by 'yyy'
- dbDriver 使用 native 会简单一些
启动命令
cd /usr/local/mycat/bin
./mycat console # 会将信息打印再屏幕上
# 或
./mycat start # 后台
mycat 节点为 192.168.0.170
server.xml 的时候提到过
- 9066 端口: 管理端口
- 8066 端口: 数据端口
因此,访问 192.168.0.170:8066 ,看是否能看到 mycat 的逻辑数据库 TESTDB,也就是对应的物理数据库(主从的) world
遇到的问题:
无法连接到物理库,手动连接的时候报错:
ERROR 1129 (HY000): Host '192.168.0.170' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'
到物理库上 flush hosts
如上,
能在逻辑库中查看到 city 表的数据
测试读写分离:
如上,
前两条分布在从节点上执行,(并非轮询)
最后一条以事务提交的 sql 在 master 上执行。

