2022-05-03
参考:https://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)负担
2. mysql 主从搭建
100 节点和 101、102 节点的主从环境搭建过程(略)
3. mycat 安装
170 节点安装 mycat
3.1 jdk
mycat 是 java 写的,所以需要先确定有 java 开发环境
yum install java
3.2 安装 mycat
虽然已经有 mycat2,但此处采用的版本是 1.6
解压
bin目录
可以执行文件
conf 目录
配置文件
log 目录
日志
4. mycat 配置
4.1 server.xml
mycat 的一些配置信息
4.1.1 <system> 标签
主要用来配置 mycat 的系统参数
<system>
...
<property name="serverPort">8066</property>
<property name="managerPort">9066</property
...
</system>
如上:
这两个就分别定义了 mycat 的数据端口(8066)和管理端口(9066)
如果后续连接到 mycat 的话,就是通过这两个端口
4.1.2 <user> 标签
配置访问 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
这个表上,没有这四种权限。
4.2 schema.xml
用于配置逻辑库、逻辑表相关信息
当应用连接到 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>
标签继续定义
4.2.2 <table> 标签
需要拆分的表在这个标签中定义
(此例中配置的账号,无需这部分,可以删除)
<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 属性,
4.3.3 <dataNode> 标签
定义数据节点, 将来的分库就是分到这些节点中.
我的理解,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
:
是否对密码加密
4.3 配置文件结构图
具体的配置如下:
server.xml
如上,配置使用 mycat 这个用户去登录 mycat,如果需要 mycat 写的话,将 readOnly 删除掉。
当然,定义的 root 用户也可以访问。
schema.xml
<mycat:schema xmlns:mycat="http://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 上创建好,
5. 检查
在上面的配置中,定义 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 # 后台
7. 测试连接
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 上执行。