MyCat 读写分离配置

这篇是基于另一篇当中 MySQL 主从复制的示例,来用 MyCat 作为数据库中间件,实现只对外暴露一个数据库连接入口的 MySQL 读写分离。
0. 前提
- 完成 MySQL 主从复制的部署(传送门)。
- 还是基于 Docker,运行一个 MyCat 容器。
- 应该就这些。
1. MyCat 容器部署
首先,下载 MyCat。由于我们要不输在容器里,所以下载 Linux 的版本。
$ wget http://dl.mycat.io/1.6.7.1/Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz
此时,得到一个 Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz
文件。为了方便后面使用,给它改个名字。
$ mv Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz mycat.tar.gz
在当前目录解压它,并把其中的 conf
目录拷贝一份,供 Docker 容器挂载,这样就不需要进入到容器里面修改 MyCat 的配置。
$ tar -zxvf mycat.tar.gz
$ cp -r mycat/conf/ conf/
准备工作完成后,开始构建容器镜像,创建一个 Dockerfile,在其中写入以下内容:
FROM openjdk:8
ADD mycat.tar.gz /usr/local/
VOLUME /usr/local/mycat/conf
ENV MYCAT_HOME=/usr/local/mycat
EXPOSE 8066 9066
CMD ["/usr/local/mycat/bin/mycat","console","&"]
逐行解释一下 Dockerfile 的内容:
- MyCat 基于 Java,因此使用
openjdk:8
镜像构建我们使用的 MyCat 镜像。 - 将下载并重命名好的
mycat.tar.gz
添加到容器的/usr/local/
目录。 - 将 MyCat 的配置文件目录
/usr/local/mycat/conf
暴露给宿主机,启动时直接映射之前宿主机上复制好的conf
目录。 - 设置环境变量
MYCAT_HOME
,值是 MyCat 的安装目录。 - 暴露 8066 和 9066 两个端口。8066 端口用于外部连接数据库,类似于 MySQL 的 3306 端口;9066 是 MyCat 的管理端口。
- 执行启动 MyCat 的命令。
在当前目录构建镜像:
$ docker build -t mycat-1.6.7.1 .
然后启动一个容器实例:
$ docker run --name mycat -p 8066:8066 -p 9066:9066 -v /path/to/conf/:/usr/local/mycat/conf/ -d mycat-1.6.7.1 --link mysql-dn-s:mysql-slave --link mysql-dn-m:mysql-master
注:以上命令中的 /path/to/conf/
指的是实际宿主机中 conf
目录的绝对路径。同时,用 --link
创建了与两个数据库之间的网络连接。
现在 MyCat 的容器已经跑起来了,但是在配置好数据源之前还不能用。
2. 修改 MyCat 配置
因为之前启动容器的时候做了配置文件目录的映射,所以我们直接在宿主机的 conf
目录中修改 MyCat 的配置。
首先修改 schema.xml
,主要内容如下:
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- MyCat 对外暴露的 schema -->
<schema name="test" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
</schema>
<!-- 数据节点,这里我们只配置读写分离的部分,因此只配置一个节点来做读写分离的示例 -->
<dataNode name="dn1" dataHost="localhost1" database="test" />
<!-- 这里的 balance=1 表示配置读写分离-->
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<!--心跳通知的查询语句,使用默认即可-->
<heartbeat>select user()</heartbeat>
<!--写库配置-->
<writeHost host="hostM" url="mysql-master:3306" user="root" password="admin123">
<!--读库配置-->
<readHost host="hostS" url="mysql-slave:3306" user="root" password="admin123" />
</writeHost>
</dataHost>
</mycat:schema>
因为本示例只演示读写分离,不涉及分区分片等配置,因此这个配置文件很简单。
下面配置 server.xml
,只需打开文件,添加一个 MyCat 的外部访问用户即可,也可配置多个,视具体情况而定:
<user name="root" defaultAccount="true">
<property name="password">admin123</property>
<property name="schemas">test</property>
</user>
以上作为演示,只配置了基本的用户名、密码和库,实际情况中,还可以配置读写权限,甚至是表级 DML 权限,具体可以查阅官方文档。
配置好后,重启容器生效。
3. 测试验证
使用与连接 MySQL 同样的方法,在宿主机上连接 MyCat:
$ mycli -hlocalhost -P8066 -uroot -padmin123
注:如果连接不成功,可能需要修改两台 MySQL 的用户认证配置:ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'admin123';
。
连接成功后,就可以像直接操作 MySQL 一样进行数据库操作了。
4. 测试读写分离
在测试读写分离时,需要查看 MyCat 的日志来确定每此操作是在哪个数据库执行的,因此,首先需要修改以下 MyCat 的日志配置文件,来让 MyCat 把这部分日志打印出来。
在 conf
目录的 log4j2.xml
文件中,修改如下内容:
<asyncRoot level="info" includeLocation="true">
将其中的日志级别设置为 debug
,修改保存后重启 MyCat 容器。
现在,进入 MyCat 容器中,使用如下命令,实时查看日志:
$ tail -f /usr/local/mycat/logs/mycat.log
不要关闭查看日志的窗口,另起一个终端,连接 MyCat 对数据进行操作,在日志中就可以看到每一步操作的 SQL 语句,以及对应的更多信息。
比如下面两条日志:
2019-09-07 08:46:42.628 DEBUG [$_NIOREACTOR-5-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:386)) - release connection MySQLConnection [id=14, lastTime=1567846002623, user=root, schema=test, old shema=test, borrowed=true, fromSlaveDB=true, threadId=380, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{select * from test}, respHandler=SingleNodeHandler [node=dn1{select * from test}, packetId=9], host=mysql-slave, port=3306, statusSync=io.mycat.backend.mysql.nio.MySQLConnection$StatusSync@230d92a6, writeQueue=0, modifiedSQLExecuted=false]
2019-09-07 08:48:23.387 DEBUG [$_NIOREACTOR-5-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:386)) - release connection MySQLConnection [id=5, lastTime=1567846103379, user=root, schema=test, old shema=test, borrowed=true, fromSlaveDB=false, threadId=587, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{insert into test(value) values(15)}, respHandler=SingleNodeHandler [node=dn1{insert into test(value) values(15)}, packetId=1], host=mysql-master, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=true]
从这两条日志中可以看出 MyCat 在读库执行了查询操作,并在写库执行了插入操作。
👍