由于mycat 在四年前已经停止了更新,所以不要用mycat来操作 mysql 8.0,容易出问题,且很难搞定.我这里是基于mysql5.6 和mycat 1.6 的版本安装使用.

什么是mycat

其实就是一个数据库中间件.协助我们管理数据库.

作用

读写分离:
其实我们使用JDBC 这样的工具, 也是可以实现读写分离的,但是这样就需要我们在代码里写很多的分支判断.如果我们借助于mycat , 就不需要写代码去分配了, 可以通过mycat 来帮我们管理.
数据分片:
对数据进行拆分, 可以分库, 也可以分表, 将数据摊分在多台服务器上.
多数据源整合:
mycat 不仅仅可以操作mysql, 也支持sql server, db2 等.

原理

其实就是拦截请求, 把拦截的请求和mycat 的配置文件里的配置进行校验,然后再分发出去.与其类似的是 nginx .

基于docker 的mycat 安装

前提条件: 要先实现mysql 的主从复制,并且mysql 的版本最好是5.6, 5.7 版本, 不要mysql 8.0 的, 否则会有不少问题的, 毕竟mycat 在四年之前就已经停止更新了. 出的问题呢,对于我们这种新手来说,不是很好搞定的.我们使用mycat 都是用于学习,基本能用上mycat 的公司, 数据量都挺大的, 是行业里的大公司, 一般都会有自己公司开发的数据库中间件.我们学会mycat的使用就可以了, 再学其他的数据库中间件,都是举一反三.如果你自己就会配置mysql的主从复制,就跳过这里,如果不会,就可以看我的另一篇笔记,我有写了的,虽然是基于mysql 8.0 的主从复制, 但是mysql 5.6 , 5.7 也是通用的.

步骤一:获取资源

1
2
3
4
5
6
在 /目录下递归创建data/mycat 目录,并切换到这个目录下.
mkdir -p /data/mycat
cd /data/mycat
下载mycat的安装包
wget http://dl.mycat.org.cn/1.6.7.1/Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz
下载成功后 , ls 查看一下, 当前目录下就有这个压缩包了

步骤二: 编写Dockerfile

是的,就在/data/mycat 目录下,用vim 创建并编写Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
vim Dockerfile
然后将下面的内容粘贴到这个Dockerfile 里面,并保存退出
FROM java:8
USER root
COPY Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz /
RUN tar -zxf /Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz
ENV MYCAT_HOME=/mycat
ENV PATH=$PATH:${MYCAT_HOME}/bin
WORKDIR $MYCAT_HOME/bin
RUN chmod u+x ./mycat
EXPOSE 8066 9066
CMD ["./mycat", "console"]

步骤三: 解压配置文件

1
2
3
此时的目录是data/mycat
tar -zxvf Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz
执行解压后, 当前目录下就会有一个mycat 目录,去里面看看是否有conf,logs , 有的话,就可以了.一般这一步都不会失败的.

步骤四: 修改mycat 的配置文件

前提条件:要进到这个解压后的mycat 目录的conf 目录下.
真正需要修改的只有三个文件,具体官方文档写的很详细;(1)schema.xml ,(2)server.xml,(3)rule.xml;
由于我们这里只做读写分离. 因此我们只需要修改schema.xml 和 server.xml 这两个文件.
修改server.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
		<!-- 这里是拥有读写 权限的账号设置,我们为了避免和mysql的root 用户重复, 就起码mycat, 密码自定义即可. schemas 是能操作的逻辑库 -->
<user name="mycat" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>

<!-- 表级 DML 权限设置 -->
<!--
<privileges check="false">
<schema name="TESTDB" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table>
</schema>
</privileges>
-->
</user>
<!-- 这里是只有只读权限的用户 -->
<user name="user">
<property name="password">user</property>
<property name="schemas">TESTDB</property>
<property name="readOnly">true</property>
</user>

</mycat:server>

修改 schema.xml 文件
我已经将用不到都删除了,避免对不小心改错了地方,对整个xml文件产生影响

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="host1" database="实际的物理库的db name" />
<!--balance的值为 0 的 时候, 不开启读写分离机制;为 1 的时候, 开启 双珠双从模式;为2 的 时候,读操作都随机分发给主机和从机;为3 的时候, 所有的读操作只发给从机, 写操作只发给主机;该注释可以去掉, 避免对文件有影响.只供你阅读-->
<dataHost name="host1" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="主服务器ip:3306" user="root"
password="该账号对应的密码">
<!-- can have multi read hosts -->
<readHost host="hostS1" url="从服务器ip:3306" user="root" password="该账号对应的密码" />
</writeHost>
</dataHost>
</mycat:schema>

步骤五: 通过Dockerfile生成mycat的镜像

1
2
cd /data/mycat/
docker build -t mycat:1.6 .

步骤六: 启动mycat 的脚本

1
2
我这里对mycat的配置文件和日志文化都进行了映射
docker run --privileged=true -p 8066:8066 -p 9066:9066 --name mycat -v /data/mycat/mycat/conf:/mycat/conf -v /data/mycat/mycat/logs:/mycat/logs -d mycat镜像的id

步骤七: 验证 mycat

1
2
3
4
5
6
docker ps 拿到mycat的容器id 
docker inspect 容器id 拿到mycat 容器的ip
docker exect -it mysql主机/从机容器的id /bin/bash
mysql -uusername(你在server.xml里自定义的用户名) -ppassword(你在server.xml里自定义的密码) -h mycat 容器的ip -P8066
登陆成功后, show databases; 就可以看到逻辑库
然后 use 逻辑库; 之后show tables; 就可以看到逻辑库映射的物理库下的tables

如有报错, 排错思路

在宿主机下的/data/mycat/mycat/logs 目录下,查看mycat.log 日志.
我曾在这里犯过的错有:
1.在schema.xml 里, 给writeHost 设置密码的时候,少了一个 “ ,导致报错了.
jvm 1| Caused by: io.mycat.config.util.ConfigException: org.xml.sax.SAXParseException; lineNumber: 13; columnNumber: 5; The value of attribute “password” associated with an element type “writeHost” must not contain the ‘<’ character.

2.映射的时候,由于目录不对导致的映射失败.
问题的表象:
mycat容器是启动了, 但是发现登陆mycat , 却只能通过原始的root 用户, 1234656 密码登陆,并且逻辑库TESTDB 下的table都是schema.xml 原始数据里的那些表.并没有把物理库给映射进去.
我当时以为是版本的原因,找了挺久的问题了. 换了mycat1.6的其他几个版本都是这样, 那么我就想,这个应该和我的映射相关.
解决思路:
我发现 /data/mycat/mycat下的logs 和conf都是空,那么就进去容器里看,去到容器里查看启动的日志.发现了提示连接错误等. 我在原本指定映射的目录下, 在容器内对应的目录里创建了的文件,都没有在宿主机上有看到新建的文件.
此时在mycat容器里找到真正的配置文件的路径和日志文件的路径, 记录下来.和原来的启动脚本相比较, 发现/mycat/conf 是mycat 容器内的真正路径, 而我的启动脚本里,用的是之前百度的时候用到的 /usr/local/mycat这样的路径, 那么这个路径和实际的路径不一样,就导致了映射失败.
随后认认真真对比了宿主机的真实数据源路径和mycat 容器内想要映射的路径, 确定无误后, 重新启动容器.
这样, 才真的启动成功了.