mycat部署(单台服务器搭建单主单从架构)
mycat部署(单台服务器搭建单主单从架构)
mycat IP规划:
#单台服务器搭建主从架构,需要创建网络使容器之间互通,再者需要固定每个容器的IP地址需要自定义一个网络,正式环境不用创建这个网络
角色 | docker名称 | IP规划 | 占用服务器监听端口 |
---|---|---|---|
master | mysql01 | 10.10.27.11 | 监听端口13311 |
salve01 | mysql02 | 10.10.27.12 | 监听端口13312 |
salve02 | mysql03 | 10.10.27.13 | 监听端口13313 |
mycat | mycat | 10.10.27.16 | 监听端口:8066为业务端口 9066为mycat管理端口 |
#MySQL 网络设置:
这里定义mysql_net为MySQL服务器自定义网络,定于网络为10.10.27.0/24,网关为10.10.27.1
(使用多台独立IP服务器,不用创建网卡,可以跳过该步骤,只需要保证服务器网络互通)
docker network create --driver bridge --subnet=10.10.27.0/24 --gateway=10.10.27.1 mysql_net
步骤一、创建MySQL docker实例
#拉取mysql镜像
docker pull mysql:5.7.36
#创建MySQL三个实例的目录
mkdir -p /data/{mysql01,mysql02,mysql03}/{conf,logs,data}
#启动mysql01容器
docker run --name mysql01 \
-p 13311:3306 \
-e [email protected] \
-e TZ=Asia/Shanghai \
--restart=always \
-v /data/mysql01/conf:/etc/mysql \
-v /data/mysql01/logs:/var/log/mysql \
-v /data/mysql01/data:/var/lib/mysql \
--network=mysql_net --ip 10.10.27.11 \
-d mysql:5.7.36
#启动mysql02容器
docker run --name mysql02 \
-p 13312:3306 \
-e [email protected] \
-e TZ=Asia/Shanghai \
--restart=always \
-v /data/mysql02/conf:/etc/mysql \
-v /data/mysql02/logs:/var/log/mysql \
-v /data/mysql02/data:/var/lib/mysql \
--network=mysql_net --ip 10.10.27.12 \
-d mysql:5.7.36
#启动mysql03容器
docker run --name mysql03 \
-p 13313:3306 \
-e [email protected] \
-e TZ=Asia/Shanghai \
--restart=always \
-v /data/mysql03/conf:/etc/mysql \
-v /data/mysql03/logs:/var/log/mysql \
-v /data/mysql03/data:/var/lib/mysql \
--network=mysql_net \
--ip 10.10.27.13 \
-d mysql:5.7.36
#查看mysql三个容器是否正常运行
docker container ls
步骤二、编辑mysql的配置文件
(这里仅添加与主从相关配置内容,其他优化与设置内容省略)
vim /data/mysql01/conf/my.cnf
[mysqld]
server_id = 11 # 一组主从组里的每个id必须是唯一值。推荐用ip最后一段,如较多
log-bin= mysql-bin # 二进制日志,后面指定存放位置。如果只是指定名字,默认存放在/var/lib/mysql下
binlog-do-db=HA #选择需要同步的数据库为HA,不加这条默认全部数据库同步。
binlog-ignore-db=mysql,information_schema #选择不需要同步数据库,建议设置
#binlog-do-db=HA #选择需要同步的数据库为HA,不加这条默认全部数据库同步。
lower_case_table_names=1 # 不区分大小写
binlog-format=ROW # 二进制日志文件格式,statement格式日志会导致一些update更新语句中的的时间不一致,特别是使用now()添加更新时间的情况,更新的事行变化使用MIXED不能识别主机变量等系统函数
log-slave-updates=True # slave更新是否记入日志
sync-master-info=1 # 值为1确保信息不会丢失
binlog-checksum=CRC32 # 效验码
master-verify-checksum=1 # 启动主服务器效验
slave-sql-verify-checksum=1 # 启动从服务器效验
bind-address = 10.10.27.11 # 监听本机网卡ip
vim /data/mysql02/conf/my.cnf
[mysqld]
server_id=12
log-bin= mysql-bin #log-bin是二进制文件
relay_log = relay-bin # 中继日志, 后面指定存放位置。如果只是指定名字,默认存放在/var/lib/mysql下
lower_case_table_names=1
vim /data/mysql03/conf/my.cnf
[mysqld]
server_id=13
log-bin= /var/lib/mysql/mysql-bin
relay_log = relay-bin # 中继日志, 后面指定存放位置。如果只是指定名字,默认存放在/var/lib/mysql下
lower_case_table_names=1
重启3个容器
docker restart mysql01
docker restart mysql02
docker restart mysql03
步骤三、创建账号(master容器(mysql01))
docker exec -it mysql01 /bin/bash
mysql -uroot [email protected]
#默认赋予所有权限,以便同步
grant all privileges on *.* to dbsync@'%' identified by 'dbsync123';
FLUSH PRIVILEGES;
#生产建议使用以下语句,将同步账号权限降到最低
grant replication slave on *.* to dbsync@'%' identified by 'dbsync123';
FLUSH PRIVILEGES;
#查看master状态
SHOW MASTER STATUS;
#状态信息如下
+------------------+----------+--------------+--------------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+--------------------------+-------------------+
| mysql-bin.000003 | 154 | | mysql,information_schema | |
+------------------+----------+--------------+--------------------------+-------------------+
1 row in set (0.00 sec)
查看master容器(mysql01)状态,查看二进制文件名为(mysql-bin.000003)和具体位置(154):
同步账号到slave容器
(mysql02、mysql03配置相同,这里已设置mysql02为例)
docker exec -it mysql02 /bin/bash
测试master的同步账号是否能登录
mysql -udbsync -pdbsync123 -h 10.10.27.11
退出10.10.27.11的MySQL连接登录
mysql -uroot [email protected]
change master to master_host='10.10.27.11',master_user='dbsync',master_password='dbsync123',master_log_file='mysql-bin.000003',master_log_pos=154;
tips:重新配置主从 (即清除之前的主从配置)
stop slave; #停止主从复制
reset master;#重置master信息
启动从服务
start slave;
show slave status\G;
#主从配置成功状态如下
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
步骤四、数据测试,查看同步情况
下载测试数据
cd /data
wget https://raw.githubusercontent.com/AlphaYu/Adnc/master/doc/adnc_usr_dev.sql
wget https://raw.githubusercontent.com/AlphaYu/Adnc/master/doc/adnc_maint_dev.sql
wget https://raw.githubusercontent.com/AlphaYu/Adnc/master/doc/adnc_cus_dev.sql
#拷贝3个sql文件到mysql01容器
docker cp /data/adnc_usr_dev.sql mysql01:/usr/adnc_usr_dev.sql
docker cp /data/adnc_maint_dev.sql mysql01:/usr/adnc_maint_dev.sql
docker cp /data/adnc_cus_dev.sql mysql01:/usr/adnc_cus_dev.sql
创建数据库并导入数据
#进入mysql01容器
docker exec -it mysql01 /bin/bash
#启动mysql client
mysql -uroot [email protected]
#创建数据库 adnc_usr_dev
CREATE DATABASE IF NOT EXISTS adnc_usr_dev CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
#导入数据
use adnc_usr_dev;
source /usr/adnc_usr_dev.sql;
#创建数据库 adnc_maint_dev
CREATE DATABASE IF NOT EXISTS adnc_maint_dev CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
#导入数据
use adnc_maint_dev;
source /usr/adnc_maint_dev.sql;
#创建数据库 adnc_cus_dev
CREATE DATABASE IF NOT EXISTS adnc_cus_dev CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
use adnc_cus_dev;
source /usr/adnc_cus_dev.sql;
#进入mysql02,mysql03检查是否同步了。
docker exec -it mysql02 /bin/bash
mysql -uroot [email protected]
use adnc_usr_dev;
select count(1) from sysuser where account='Alpha2008';
步骤五、docker安装Mycat
mycat目前稳定版本是1.6.7.x版本,本文选择了最新的1.6.7.6。
1.下载mycat安装包
#新建目录
mkdir /data/mycat/logs
#切换目录
cd /data/mycat
#下载mycat release1.6.7.6到当前目录
wget http://dl.mycat.org.cn/1.6.7.6/20201126013625/Mycat-server-1.6.7.6-release-20201126013625-linux.tar.gz
mv Mycat-server-1.6.7.6-release-20201126013625-linux.tar.gz mycat1.6.7.6.tar.gz
#解压conf目录到当前目录,因为使用docker直接挂载conf目录会报错,mycat启动时需要依赖conf目录中的文件。
tar -zxvf mycat1.6.7.6.tar.gz -C /data/ mycat/conf
2.编辑配置文件
调整/data/mycat/conf目录中的server.xml 与 schema.xml 两个核心配置文件。
便于理解这里做了一个图:
server.xml 关键节点修改
这里设置mycat登录帐号密码如下:
管理账号:mycatroot 密码:[email protected]
只读账号:onlyuser 密码:[email protected]
<!-- mycat的账号,管理权限账号 -->
<user name="mycatroot" defaultAccount="true">
<!-- 密码 -->
<property name="password">[email protected]</property>
<!-- 该账号可以访问的逻辑库,对应schema.xml文件的schema节点的name-->
<property name="schemas">adnc_usr_dev,adnc_maint_dev,adnc_cus_dev</property>
<property name="defaultSchema">adnc_usr_dev</property>
</user>
<!-- mycat的普通账号,设置readOnly表示只读权限账号 -->
<user name="onlyuser">
<!-- 密码 -->
<property name="password">[email protected]</property>
<!-- 该账号可以访问的逻辑库,对应schema.xml文件的schema节点的name-->
<property name="schemas">adnc_usr_dev,adnc_maint_dev,adnc_cus_dev</property>
<!-- 设置只读账号 -->
<property name="readOnly">true</property>
<property name="defaultSchema">adnc_maint_dev</property>
</user>
schema.xml 配置详情
(目前仅是数据库库级别负载,表级别还在学习)
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- 配置3个逻辑库-->
<!-- adnc_usr_dev、adnc_maint_dev、adnc_cus_dev逻辑数据库名称(这里取名和真实数据库名称一致,为了方便辨认与数据查询维护)-->
<!-- dn_usr、dn_maint、dn_cus数据库节点名,一个数据节点管理多个相同的库的真实数据库进行读写分配-->
<schema name="adnc_usr_dev" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn_usr"></schema>
<schema name="adnc_maint_dev" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn_maint"></schema>
<schema name="adnc_cus_dev" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn_cus"></schema>
<!-- 逻辑库对应的真实数据库 -->
<!-- dh_adnc,表示定义逻辑数据库主机地址名称 -->
<dataNode name="dn_usr" dataHost="dh_adnc" database="adnc_usr_dev" />
<dataNode name="dn_maint" dataHost="dh_adnc" database="adnc_maint_dev" />
<dataNode name="dn_cus" dataHost="dh_adnc" database="adnc_cus_dev" />
<!--真实数据库所在的服务器地址,这里配置了1主2从。主服务器(hostM1)宕机会自动切换到(hostS1) -->
<dataHost name="dh_adnc" maxCon="1000" minCon="10" balance="1 " writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="10.10.27.11:3306" user="root" password="[email protected]" >
<readHost host="hostS2" url="10.10.27.13:3306" user="root" password="[email protected]" />
</writeHost>
<writeHost host="hostS1" url="10.10.27.12:3306" user="root" password="[email protected]" />
</dataHost>
</mycat:schema>
关于schema.xml
做几点简单说明:
- dataHost下的balance属性,也是通过此属性配置读写分离的类型:
- balance="0", 不开启读写分离机制,所有读操作都发送到当前可用的 writeHost 上。
- balance="1",全部的 readHost 与 stand by writeHost 参与 select 语句的负载均衡,简单地说,当双主双从模式(M1->S1,M2->S2,并且M1与M2 互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡(双主双从适用)
- balance="2",所有读操作都随机的在 writeHost、readhost 上分发。
- balance="3",所有读请求随机的分发到 readhost 执行,writerHost 不负担读压力。(单主单从作读写分离适用)
writeType="0": 所有写操作发送到配置的第一个writeHost,第一个挂了切到还生存的第二个writeHost,重新启动后以切换后的为准,切换记录在配置文件中:dnindex.properties
switchType="1":
- 1 默认值,自动切换。
- -1 表示不自动切换
- 2 基于 MySQL 主从同步的状态决定是否切换。
下载dockerfile
由于mycat官方并没有提供docker镜像,我们需要自己编写dockerfile文件打包镜像。
#下载dockerfile文件到当前目录
wget https://raw.githubusercontent.com/AlphaYu/Adnc/master/doc/mycat/Dockerfile
#如果下载失败,请手动下载并上传到/data/mycat目录,文件地址如下
#https://github.com/AlphaYu/Adnc/blob/master/doc/mycat/Dockerfile
mycat部署
mycat 服务器地址为:10.10.27.16
当前配置目录结构如下:(仅显示主要配置文件和目录,部分不常用文件被忽略删减)
/data/mycat
├── conf
│ ├── rule.xml
│ ├── schema.xml
│ ├── schema.xml.bak
│ ├── server.xml
│ ├── server.xml.bak
├── logs
└── Dockerfile
创建mycat镜像与容器
#创建镜像文件
docker build -t mycat:1.6.7.6 .
创建成功后再进行运行
docker run --name mycat \
--privileged=true \
--restart=always \
-p 8066:8066 \
-p 9066:9066 \
-v /data/mycat/conf:/usr/local/mycat/conf \
-v /data/mycat/logs:/usr/local/mycat/logs \
--network=mysql_net --ip 10.10.27.16 \
-d mycat:1.6.7.6
运行容器并挂载配置文件目录与日志目录
#-v /data/mycat/conf:/usr/local/mycat/conf #挂载配置文件目录
#-v /data/mycat/logs:/usr/local/mycat/logs #挂载日志目录
#--network=mysql_net --ip 10.10.27.16
#mysql_net是自建的bridge网络,如果使用docker默认网络,不需要这段,如果采用host模式还是端口映射对外访问,也不需要指定IP
docker mycat验证
进入mysql容器
docker exec -it mysql01 /bin/bash
登录mycat,10.10.27.16 是指mycat容器的Ip地址,如果容器没有指定固定Ip,你的可能不一样,请注意。
mysql -umycatroot [email protected] -P8066 -h10.10.27.16
显示所有数据库
show databases;
多次执行下面的sql,观察hostname的变化。
select @@hostname;
扩展内容
标签权限控制
1.user标签
<!-- 应用程序连接中间件逻辑库的用户名 -->
<user name="user">
<!-- 应用程序连接中间件逻辑库的密码 -->
<property name="password">user</property>
<!-- 逻辑库名称 -->
<property name="schemas">TESTDB</property>
<!-- true:只读;默认false:可读可写 -->
<property name="readOnly">true</property>
<!-- 默认逻辑库名称 -->
<property name="defaultSchema">TESTDB</property>
</user>
2.privileges标签
privileges 标签可以对逻辑库(schema)、表(table)进行精细化的DML权限控制
<user name="mycat" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>
<property name="defaultSchema">TESTDB</property>
<!--No MyCAT Database selected 错误前会尝试使用该schema作为schema,不设置则为null,报错 -->
<!-- 表级 DML 权限设置 -->
<!-- 是否开启权限检查,默认false -->
<privileges check="false">
<schema name="TESTDB" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table>
</schema>
</privileges>
</user>
DML权限 | 增加insert | 更新update | 查询select | 删除delete |
---|---|---|---|---|
0000 | N | N | N | N |
0010 | N | N | Y | N |
1110 | Y | Y | Y | N |
1111 | Y | Y | Y | Y |
SQL拦截
firewall标签用来定义防火墙;firewall下whitehost标签用来定义IP白名单 ,blacklist用来定义SQL黑名单。
1.白名单
设置白名单,实现指定的某主机某用户可以访问Mycat
<!-- 全局SQL防火墙设置 -->
<firewall>
<!--白名单 -->
<whitehost>
<!--白名单可以使用通配符%或着*-->
<!--对于127.0.0.1能以root账户登录-->
<host host="1*7.0.0.*" user="root"/>
</whitehost>
<blacklist check="false">
</blacklist>
</firewall>
2.黑名单
设置黑名单,实现Mycat对具体SQL操作的拦截,如增删改查等操作的拦截。
<!-- 全局SQL防火墙设置 -->
<firewall>
<!--白名单 -->
<whitehost>
<!--白名单可以使用通配符%或着*-->
<!--对于127.0.0.1能以root账户登录-->
<host host="1*7.0.0.*" user="root"/>
</whitehost>
<!-- 黑名单 -->
<blacklist check="true">
<!-- 禁止root用户进行删除操作 -->
<property name="deleteAllow">false</property>
</blacklist>
</firewall>
配置项 | 缺省值 | 描述 |
---|---|---|
selelctAllow | true | 是否允许执行SELECT语句 |
deleteAllow | true | 是否允许执行DELETE语句 |
updateAllow | true | 是否允许执行UPDATE语句 |
insertAllow | true | 是否允许执行INSERT语句 |
insertAllow | true | 是否允许执行INSERT语句 |
createTableAllow | true | 是否允许创建表 |
setAllow | true | 是否允许使用set语法 |
alterTableAllow | true | 是否允许执行Alter Table语句 |
dropTableAllow | true | 是否允许修改表 |
commitAllow | true | 是否允许执行commit操作 |
rollbackAllow | true | 是否允许执行roll back操作 |