MyCat 读写分离配置| 8月更文挑战

199 阅读3分钟

这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战

这篇是基于另一篇当中 MySQL 主从复制的示例,来用 MyCat 作为数据库中间件,实现只对外暴露一个数据库连接入口的 MySQL 读写分离。

0. 前提

  1. 完成 MySQL 主从复制的部署(传送门)。
  2. 还是基于 Docker,运行一个 MyCat 容器。
  3. 应该就这些。

1. MyCat 容器部署

首先,下载 MyCat。由于我们要部署在 Docker 容器里,所以下载 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 的内容:

  1. MyCat 基于 Java,因此使用 openjdk:8 镜像构建我们使用的 MyCat 镜像。
  2. 将下载并重命名好的 mycat.tar.gz 添加到容器的 /usr/local/ 目录。
  3. 将 MyCat 的配置文件目录 /usr/local/mycat/conf 暴露给宿主机,启动时直接映射之前宿主机上复制好的 conf 目录。
  4. 设置环境变量 MYCAT_HOME,值是 MyCat 的安装目录。
  5. 暴露 8066 和 9066 两个端口。8066 端口用于外部连接数据库,类似于 MySQL 的 3306 端口;9066 是 MyCat 的管理端口。
  6. 执行启动 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 在读库执行了查询操作,并在写库执行了插入操作。