Mysql主从复制与读写分离
目录
案例分析
案例概述
MySQL主从复制原理和概述
复制的工作过程中
MySQL读写分离原理
目前较为常见的MySQL读写分离分为两种
基于程序代码内部实现
基于中间代理商实现
案例环境
案例实现思路
案例实施
搭建MySQL主从复制
配置防火墙和SELINUX内核
安装MYSQL数据库
基础环境准备
安装 MySQL 依赖的软件包
创建运行 MySQL 程序的用户
二进制安装
设定配置文件
配置 systemctl 方式启动
配置master主服务器
重启mysql服务
配置 Slave 从服务器
验证主从复制效果
搭建 MySQL 读写分离
安装mycat2
安装并配置mycat软件
配置MYcat读写分离
创建 Mycat2 工作所必须的账号
启动 Mycat2
Mycat2 配置读写分离
第二步:创建Mycat集群
验证mycat读写分离
测试写操作
案例分析
案例概述
在实际的生产环境中,如果对数据库的读和写都在同一个数据库服务器中操作,无论是在安全性、高可用性还是高并发等各个方面都是完全不能满足实际需求的。因此,一般来说都是通过主从复制(Master - Slave)来同步数据,再通过读写分离来提升数据库并发负载能力的方案来进行部署与实施。
一台主 MySQL 服务器带两台从 MySQL 服务器做数据复制,前端应用在进行数据库写操作时,对主服务器进行操作,在进行数据库读操作时,对两台从服务器进行操作,这样大量减轻了对主服务器的压力。
MySQL主从复制原理和概述
MySQL 的主从复制和 MySQL 的读写分离两者有着紧密联系,首先要部署主从复制,只有主从复制完成了,才能在此基础上进行数据的读写分离。
在实际的生产环境中,对数据库的读和写都在同一个数据库服务器中,是不能满足实际需求的。无论是在安全性、高可用性还是高并发等各个方面都是完全不能满足实际需求的。因此,通过主从复制的方式来同步数据,再通过读写分离来提升数据库的并发负载能力。有点类似于rsync,但是不同的是rsync是对磁盘文件做备份,而mysql主从复制是对数据库中的数据、语句做备份。
MySQL支持的复制类型
基于语句的复制:在主服务器上执行的 SQL 语句,在从服务器上执行同样的语句,MySQL 默认采用基于语句的复制,效率比较高;
基于行的复制:把改变的内容复制过去,而不是把命令在从服务器上执行一遍;
混合类型的复制:默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。
复制的工作过程中
- 在每个事务更新数据完成之前,Master 将这些改变记录进二进制日志。写入二进制日志完成后,Master 通知存储引擎提交事务。
- Slave 将 Master 的 Binary log 复制到其中继日志(Relay log)。首先,Slave 开始一个工作线程--I/0 线程,I/0 线程在 Master 上打开一个普通的连接,然后开始 Binlog dump process。Binlog dump process 从 Master 的进制日志中读取事件,如果已经跟上 Master,它会睡眠并等待 Master 产生新的事件。I/0 线程将这些事件写入中继日志。
- SQL slave thread(sQL 从线程)处理该过程的最后一步。SQL 线程从中继日志读取事件,并重放其中的事件而更新 Slave 数据,使其与 Master 中的数据保持一致。只要该线程与 I/0 线程保持一致,中继日志通常会位于0S 的缓存中,所以中继日志的开销很小。复制过程有一个很重要的限制,即复制在Save 上是串行化的,也就是说 Master 上的并行更新操作不能在 Slave 上并行操作。
- 复制过程有个很重要的限制,即复制在Slave上是串行化的,也就是说Master上的并行更新操作不能在Slave上并行操作
MySQL读写分离原理
简单来说,读写分离(图6.3)就是只在主服务器上写,只在从服务器上读。基本的原理是让主数据库处理事务性查询,而从数据库处理 select 查询。数据库复制被用来把主数据库上事务性查询导致的变更同步到集群中的从数据库。
目前较为常见的MySQL读写分离分为两种
基于程序代码内部实现
在代码中根据 select、insert 进行路由分类,这类方法也是目前生产环境应用最广泛的。优点是性能较好,因为在程序代码中实现,不需要增加额外的设备作为硬件开支;缺点是需要开发人员来实现,运维人员无从下手。
基于中间代理商实现
- 代理一般位于客户端和服务器之间,代理服务器接到客户端请求后通过判断后转发到后端数据库,有两个代表性程序。
- MySQL-Proxy。MySQL-Proxy 为 MySQL 开源项目,通过其自带的 lua 脚本进行 SQL 判断,虽然是 MySQL 官方产品,但是 MySQL 官方并不建议将 MySQL-Proxy 用到生产环境;
- Amoeba。由陈思儒开发,作者曾就职于阿里巴巴。该程序由 Java 语言进行开发,阿里巴巴将其用于生产环境。它不支持事务和存储过程。经过上述简单的比较,通过程序代码实现 MySQL 读写分离自然是一个不错的选择,但是并不是所有的应用都适合在程序代码中实现读写分离,像一些大型复杂的 Java 应用,如果在程序代码中实现读写分离对代码改动就较大。所以,像这种应用一般会考虑使用代理层来实现。本章后续案例通过 Amoeba 实现;
- MyCAT 是一款开源的分布式关系型数据库中间件,主要用于解决大规模数据存储和高效查询的需求。它支持分布式 SQL 查询,兼容 MySQL 通信协议,能够通过数据分片提高数据查询处理能力。MyCAT 的前端用户可以将其视为一个数据库代理,使用 MySQL 客户端工具和命令行访问,而后端则可以通过 MySQL 原生协议与多个 MySQL 服务器通信,或者使用 JDBC 协议与大多数主流数据库服务器通信。
案例环境
本案例环境使用五台服务器模拟搭建,具体的网络拓扑如图 6.4 所示。案例环境如表 6-1 所示。
主机 | 操作系统 | IP 地址 | 应用 |
---|---|---|---|
Master | openEuler 24.03 | 192.168.10.101 | Mysql-server |
Slave1 | openEuler 24.03 | 192.168.10.102 | Mysql-server |
Slave2 | openEuler 24.03 | 192.168.10.103 | Mysql-server |
Mycat | openEuler 24.03 | 192.168.10.104 | Mycat2 |
客户端 | openEuler 24.03 | 192.168.10.105 | mysql |
本案例要求通过 Mycat2 实现 MySQL 数据库请求的读写分离。
案例实现思路
-
安装 MySQL 数据库;
-
配置 MySQL 主从复制;
-
安装并配置 Mycat2;
-
客户端测试读写分离。
案例实施
搭建MySQL主从复制
在所有节点进行时间同步
[root@bogon ~]# dnf -y install ntpdate[root@bogon ~]# ntpdate ntp1.aliyun.com4 Jun 09:28:46 ntpdate[2380]: step time server 121.199.69.55 offset +56334.683387 s
配置防火墙和SELINUX内核
在每台服务器上关闭firewalld或在firewalld上开放通行端口
[root@bogon ~]# systemctl stop firewalld[root@bogon ~]# systemctl disable firewalld[root@bogon ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config [root@bogon ~]# setenforce 0setenforce: SELinux is disabled
安装MYSQL数据库
在 Master、Slave1、Slave2 服务器上安装 MySQL 数据库。本案例采用二进制安装
基础环境准备
如果采用 OpenEuler minimal 安装的系统,在使用前需要安装一些基础软件包工具。
[root@master ~]# dnf -y install gcc vim wget net-tools lrzsz tar
安装 MySQL 依赖的软件包
[root@master ~]# dnf install -y libaio numactl openssl ncurses-compat -libs
创建运行 MySQL 程序的用户
[root@master ~]# useradd -M -s /sbin/nologin mysql
[root@master ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
[root@master ~]# setenforce 0
[root@master ~]# systemctl disable firewalld
[root@master ~]# systemctl stop firewalld
二进制安装
二进制安装的版本采用跟上面编译安装的版本一样 MySQL 8.0.36。首先需要下载该软件包或者提前上传,然后再解压进行配置。
[root@master ~]# tar xJf mysql-8.0.36-linux-glibc2.28-x86_64.tar.xz
[root@master ~]# mv mysql-8.0.36-linux-glibc2.28-x86_64 /usr/local/mysql
[root@master ~]# mkdir /usr/local/mysql/data
[root@master ~]# chown -R mysql:mysql /usr/local/mysql/data
[root@master ~]# cd /usr/local/mysql/bin
[root@master ~]# ./mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data2025-03-19T13:28:28.959612 Z 0 [System] [MY-013169] [Server] /usr/local/mysql/bin/mysqld (mysqld 8.0.36) initializing of server in progress as process 6414
2025-03-19T13:28:28.968182 Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2025-03-19T13:28:29.141927 Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2025-03-19T13:28:30.473508 Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: Xr6:gub8?/8
此次初始化没有采用无密码模式,因此会生成初始随机密码,需要保存,用以后续登录 mysql 数据库使用
设定配置文件
MySQL 的配置文件跟上面编译安装的配置文件类似。
[root@master ~]# vim /etc/my.cnf[client]
socket=/usr/local/mysql/data/mysql.sock
[mysqld]
socket=/usr/local/mysql/data/mysql.sock
bind-address = 0.0.0.0
skip-name-resolve
port = 3306
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
max_connections=2048
character-set-server=utf8
default-storage-engine=INNODB
max_allowed_packet=16M
将 MySQL 的可执行文件写入环境变量中。
[root@master ~]# echo "export PATH=$PATH:/usr/local/mysql/bin" >> /etc/profile
[root@master ~]# . /etc/profile // 使配置在当前 Shell 中生效
配置 systemctl 方式启动
将 MySQL 添加成为系统服务,通过使用 systemctl 来管理。在 /usr/local/mysql/support-files 目录下找到 mysql.server 文件,将其复制到 /etc/rc.d/init.d 目录下,改名为 mysqld 并赋予可执行权限。
[root@master ~]# cp /usr/local/mysql/support-files/mysql.server /etc/rc.d/init.d/mysqld
[root@master ~]# chmod +x /etc/rc.d/init.d/mysqld
编辑生成 mysqld.service 服务,通过 systemctl 方式来管理。
[root@master ~]# vim /lib/systemd/system/mysqld.service[Unit]
Description=mysqld
After=network.target[Service]
Type=forkingExecStart=/etc/rc.d/init.d/mysqld start
ExecReload=/etc/rc.d/init.d/mysqld restart
ExecStop=/etc/rc.d/init.d/mysqld stop
PrivateTmp=true[Install]
WantedBy=multi-user.target[root@master ~]# systemctl daemon-reload
[root@master ~]# systemctl enable mysqld
[root@master ~]# systemctl start mysqld
[root@master ~]# netstat -tunlp |grep 3306
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 1785/mysqld[root@master ~]# mysqladmin -u root password 'pwd123' // 为 root 用户设置密码
配置master主服务器
在/etc/my.cnf中修改添加下面内容[root@bogon ~]# vim /etc/my.cnf [mysqld] log-bin=/usr/local/mysql/data/mysql-bin #启用二进制日志(Binary LOG)并指定器存储路径binlog_format = MIXED #定义二进制的记录格式为混合格式server-id=1 #为mysql实例分配一个唯一的服务器表示符
重启mysql服务
[root@bogon ~]# systemctl restart mysqld
登录MySQL程序,给与服务器用户授权
[root@bogon ~]# mysql -uroot -ppwd123mysql> alter user 'root'@'localhost' identified with mysql_native_password by 'pwd123'-> ;Query OK, 0 rows affected (0.01 sec)mysql> create user 'myslave'@'%' identified by '123456';Query OK, 0 rows affected (0.02 sec)mysql> grant replication slave on *.* to 'myslave'@'%';Query OK, 0 rows affected (0.00 sec)mysql> alter user 'myslave'@'%' identified with mysql_native_password by '123456';Query OK, 0 rows affected (0.00 sec)
MySQL默认使用caching_sha2_password 认证插件,将mysql_native_password替换为旧版认证插件,确保数据库能够兼容
mysql> flush privileges; #刷新配置Query OK, 0 rows affected (0.01 sec)mysql> show master status;+------------------+----------+--------------+------------------+-------------------+| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |+------------------+----------+--------------+------------------+-------------------+| mysql-bin.000001 | 1438 | | | |+------------------+----------+--------------+------------------+-------------------+1 row in set (0.00 sec)
file列为为日志名,position列显示偏移量,这两个值在后面配置从服务器需要,slave应从该节点上进行新的更新。
配置 Slave 从服务器
在 Slave1、Slave2 服务器上面分别执行下面步骤。
/etc/my.cnf 中修改或者增加下面内容,这里要注意 server-id 不能相同。
[root@localhost ~]# vim /etc/my.cnf
server-id = 2 // 增加,唯一的服务器标识符,集群内不能冲突
重启 MySQL 服务。
[root@localhost ~]# systemctl restart mysqld
登录 MySQL,配置同步。
按主服务器结果更改下面命令中 master_log_file 和 master_log_pos 参数。
[root@localhost ~]# mysql -uroot -p
mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456';
Query OK, 0 rows affected (0.01 sec)
mysql> change master to master_host='192.168.10.101',master_user='myslave', master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=157;
Query OK, 0 rows affected, 8 warnings (0.01 sec)
启动同步。
mysql>start slave;Query OK, 0 rows affected (0.00 sec)
查看 Slave 状态,确保以下两个值为 YES
mysql> \show slave status\G*************************** 1. row ***************************Slave_IO_State: Connecting to sourceMaster_Host: 192.168.10.102Master_User: mysqlveMaster_Port: 3306Connect_Retry: 60Master_Log_File: mysql-bin.000001Read_Master_Log_Pos: 1438Relay_Log_File: bogon-relay-bin.000001Relay_Log_Pos: 4Relay_Master_Log_File: mysql-bin.000001Slave_IO_Running: ConnectingSlave_SQL_Running: YesReplicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table:
验证主从复制效果
在主,从服务器上登录MySQL
[root@bogon ~]# mysql -u root -p pwd123
在主服务上新建数据库db_test
mysql> create database db_test;Query OK, 1 row affected (0.01 sec)
在从服务器上查看是否添加
mysql> show databases;+--------------------+| Database |+--------------------+| dd_test || information_schema || mysql || performance_schema || sys || test |+--------------------+6 rows in set (0.00 sec)
搭建 MySQL 读写分离
- MyCAT 是目前最流行的分布式数据库中间插件,是一个开源的分布式数据库系统,是一个实现了 MySQL 协议的服务器。前端用户可以把它看作一个数据库代理,用 MySQL 客户端工具和命令行访问,其后端可以用 MySQL 原生协议与多个 MySQL 服务器通信,也可以用 JDBC 协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为 N 个小表,存储在后端 MySQL 服务器里或者其他数据库里。
- MyCAT 发展到目前,已经不是一个单纯的 MySQL 代理了,它的后端可以支持 MySQL、SQL Server、Oracle、DB2、PostgreSQL 等主流数据库,也支持 MongoDB 这种新型 NoSQL 方式的存储。未来,它还会支持更多类型的存储。
- 不过,无论是哪种存储方式,在最终用户看,MyCAT 里都是一个传统的数据库表,支持标准的 SQL 语句进行数据的操作,这样一来,对前端业务系统来说,可以大幅降低开发难度,提升开发速度。
安装mycat2
mycat依赖与java,因此需要在读写分离代理层系统安装java环境
[root@bogon ~]# dnf -y install jdk-8u171-linux-x64.rpm
安装并配置mycat软件
unzip解压mycat安装包,并解压到/usr/local下
[root@bogon ~]# unzip mycat2-install-template-1.20.zip -d /usr/local
为简化输入,将系统环境变量转移到“/etc/profile",最后一行添加mycat安装目录的可执行文件所在绝对路径,更新后的”/etc/profile“文件的最后一行的完整内容为:
[root@bogon ~]# echo 'export PATH=$PATH:/usr/local/mycat/bin' >>/etc/profile
[root@bogon ~]# source /etc/profile
把依赖包mycat2-1.21-release-jar-with-dependencies.jar 和 mysql-connector-java-8.0.18.jar 转移到/usr/local/mycat/lib目录中
[root@bogon ~]# cp mycat2-1.21-release-jar-with-dependencies.jar mysql-connector-java-8.0.18.jar /usr/local/mycat/lib
为mycat命令添加执行权限
[root@bogon mycat]# chmod -R +x /usr/local/mycat/bin
到目前为止,安装的步骤基本上算是完成了,任意命令行下执行指令 “mycat -h”,验证安装的正确性
[root@bogon mycat]# mycat -hUsage: /usr/local/mycat/bin/mycat { console | start | stop | restart | status | dump }
配置MYcat读写分离
mycat2读写分离配置可分为:创建数据库连接账号,启动Mycat2与读写分离配置等配置,接下来配置。
创建 Mycat2 工作所必须的账号
启动 Mycat2 服务,需要有真实的数据库服务器支撑才能运行,因此,需要在 MySQL 服务器(其它被 Mycat2 支持的数据库也如此)创建账号并给账号授权,然后在 Mycat2 所在的宿主系统用 MySQL 客户端用创建好的账号远程进行连接,验证账号的有效性和正确性。
在前边的章节,我们已经做好了 MySQL 数据库间的主从同步,因此创建 Mycat2 所需账号的操作只需也只能在主数据库上进行,具体的指令如下:
mysql> create user 'mycat'@'%' identified by 'pwd123';Query OK, 0 rows affected (0.01 sec)mysql> grant all on *.* to 'mycat'@'%';Query OK, 0 rows affected (0.02 sec)mysql> alter user 'mycat'@'%' identified with mysql_native_password BY 'pwd123';Query OK, 0 rows affected (0.01 sec)mysql> flush privileges;Query OK, 0 rows affected (0.00 sec)
启动 Mycat2
与 Mycat1.X 版本相比,Mycat2 的配置基本不需要手动去修改配置文件,而是可以在 Mycat2 启动之后,登录 Mycat 管理后台,用 SQL 指令或者客户端工具进行配置。在启动 Mycat2 之前,需要对原型库的数据源做相应的修改,修改的项主要是主数据库的连接信息,一个完整的修改过的原型数据源文件 “/usr/local/mycat/conf/datasources/prototypeDs.datasource.json” 的内容如下:被修改过的内容,以红色字显示
[root@bogon mycat]# vim /usr/local/mycat/conf/datasources/prototypeDs.datasource.json "name":"prototypeDs","password":"pwd123","type":"JDBC","url":"jdbc:mysql://192.168.10.102:3306/mysql?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8","user":"mycat","weight":0
因为已经对系统变量做了设置,所以在任意路径执行 “mycat start” 就可以启动 Mycat2。在 Mycat2 的安装目录 “/usr/local/mycat” 下,存在目录 “logs”,打开此目录中的日志文件 “wrapper.log”,可了解 Mycat2 服务的运行状况
[root@bogon mycat]# mycat startStarting mycat2...[root@bogon mycat]# ss -tnl | grep 8066LISTEN 0 4096 *:8066 *:* [root@bogon mycat]# tail -f /usr/local/mycat/logs/wrapper.log INFO | jvm 1 | 2025/06/04 16:28:14 | 2025-06-04 16:28:14,878[INFO]io.mycat.replica.heartbeat.HeartbeatFlow.sendDataSourceStatus:71prototypeDs heartStatus DatasourceStatus(status=OK_STATUS, isSlaveBehindMaster=false, dbSynStatus=DB_SYN_NORMAL, master=true)INFO | jvm 1 | 2025/06/04 16:28:15 | 2025-06-04 16:28:15,806[INFO]io.mycat.config.MycatRouterConfigOps.recoveryXA:728readXARecoveryLog startINFO | jvm 1 | 2025/06/04 16:28:15 | 2025-06-04 16:28:15,868[INFO]io.mycat.vertx.VertxMycatServer.lambda$start$1:120Mycat Vertx server bb409944-7796-483b-9ddf-ed1b71667acd started up.INFO | jvm 1 | 2025/06/04 16:28:15 | 2025-06-04 16:28:15,868[INFO]io.mycat.vertx.VertxMycatServer.lambda$start$1:120Mycat Vertx server c9ebf9bd-7cdb-4961-a9c8-a35785ef6771 started up.
用mysql客户端工具连接mycat的服务器端口tcp 8066,用户名与密码在配置文件 /usr/local/mycat/conf/users/root.user.json
[root@bogon mycat]# cat /usr/local/mycat/conf/users/root.user.json {"dialect":"mysql","ip":null,"password":"123456","transactionType":"xa","username":"root"
用命令行连接 Mycat 管理后台的指令为 “mysql -uroot -p123456 -P8066 -h192.168.10.104”,进入用户交互界面,表明 Mycat2 运行正常,可在此交互界面进行读写分离配置。
[root@bogon ~]# mysql -uroot -p123456 -P8066 -h192.168.10.104mysql: [Warning] Using a password on the command line interface can be insecure.Welcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 0Server version: 5.7.33-mycat-2.0 MySQL Community Server - GPLCopyright (c) 2000, 2024, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respectiveowners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql>
Mycat2 配置读写分离
两种配置 MySQL 读写分离的方法,一种是直接在 Mycat 的配置目录 “/usr/local/mycat/conf” 的子目录编辑相关的文本文件(Mycat1.x 版本只用这种方法);另一种登录到 Mycat 交互界面,用特殊语法的 SQL 命令进行配置。本教程采用第二种方法,直接在 Mycat 的交互界面输入命令。
第一步:Mycat 增加数据源
需要正确输入的数据主要包括:MySQL 主从数据库的 IP 地址、数据库库名(schema)、数据库账号、数据库密码(生产数据库请使用复杂密码)、实例类型(READ、WRITE 或 READ_WRITE)。下边是添加一个主库源和两个从库源的具体指令:
[root@bogon ~]# mysql -uroot -p123456 -P8066 -h192.168.10.104
增加主库master
mysql> /*+ mycat:createDataSource{-> "name":"master",-> "url":"jdbc:mysql://192.168.10.102:3306/mysql?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true",-> "instanceType":"WRITE",-> "user":"mycat",-> "password":"pwd123"-> }*/;Query OK, 0 rows affected (0.05 sec)
增加从库slave1
mysql> /*+ mycat:createDataSource{-> "name":"slave1",-> "url":"jdbc:mysql://192.168.10.103:3306/mysql?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true",-> "instanceType":"READ",-> "user":"mycat",-> "password":"pwd123"-> }*/;Query OK, 0 rows affected (0.01 sec)
查看数据源信息
mysql> /*+ mycat:showDataSources{} */\G*************************** 3. row ***************************NAME: slave1USERNAME: mycatPASSWORD: pwd123MAX_CON: 1000MIN_CON: 1EXIST_CON: 0USE_CON: 0MAX_RETRY_COUNT: 5MAX_CONNECT_TIMEOUT: 30000DB_TYPE: mysqlURL: jdbc:mysql://192.168.10.103:3306/mysql?serverTimezone=Asia/Shanghai&useUnicode=true&useJDBCCompliantTimezoneShift=true&characterEncoding=UTF-8&autoReconnect=trueWEIGHT: 0INIT_SQL: INIT_SQL_GET_CONNECTION: trueINSTANCE_TYPE: READ
如数据源配置有误可使用“ /*+ mycat:resestConfig{} */; " 进行重置
正确执行完上面三条 SQL 语句以后,在目录 “/usr/local/mycat/conf/datasources” 下自动生成三个文本文件,文件名以已经执行的 SQL 语句中 “name” 的键值做前缀
[root@bogon ~]# ll /usr/local/mycat/conf/datasources/总计 12-rw-r--r-- 1 root root 469 6月 4日 19:30 master.datasource.json-rw-r--r-- 1 root root 423 6月 4日 20:01 prototypeDs.datasource.json-rw-r--r-- 1 root root 468 6月 4日 19:53 slave1.datasource.json
第二步:创建Mycat集群
在本案例中,集群环境为一个主库与两个从库,创建mycat集群的sql语句如下:
mysql> /*+ mycat:createCluster{-> "name":"cls01",-> "masters":["master"],-> "replicas":["slave1"]-> }*/;Query OK, 0 rows affected (0.03 sec)
上述SQL语句执行后,可在目录 查看mycat配置文件
查看并修改集群配置
[root@bogon ~]# vim /usr/local/mycat/conf/clusters/cls01.cluster.json {"clusterType":"MASTER_SLAVE","heartbeat":{"heartbeatTimeout":1000,"maxRetryCount":3,"minSwitchTimeInterval":300,"showLog":false,"slaveThreshold":0.0},"masters":[ #主节点"master"],"maxCon":2000,"name":"cls01","readBalanceType":"BALANCE_ALL_READ", #请修改为BALANCE_ALL_READ,所有显示读请求路由到从节点(事务除外)"balance" :1, #没有请添加,所有从节点按固定顺序依次接收请求"replicas":[ #从节点"slave1"],"switchType":"SWITCH"}
修改负载均衡的默认策略为轮询
[root@bogon ~]# cat /usr/local/mycat/conf/server.json {"loadBalance":{"defaultLoadBalance":"BalanceRoundRobin", #修改为 BalanceRoundRobin 变成轮询查询"loadBalances":[]},"mode":"local","properties":{},"server":{"bufferPool":{},"idleTimer":{"initialDelay":3,"period":60000,"timeUnit":"SECONDS"},"ip":"0.0.0.0","mycatId":1,"port":8066,"reactorNumber":8,"tempDirectory":null,"timeWorkerPool":{"corePoolSize":0,"keepAliveTime":1,"maxPendingLimit":65535,"maxPoolSize":2,"taskTimeout":5,"timeUnit":"MINUTES"},"workerPool":{"corePoolSize":1,"keepAliveTime":1,"maxPendingLimit":65535,"maxPoolSize":1024,"taskTimeout":5,"timeUnit":"MINUTES"}}}
修改配置后需重启mycat
[root@bogon ~]# mycat restart^[[DStopping mycat2...Stopped mycat2.Starting mycat2...
验证mycat读写分离
登录mycat集群,创建测试表
mysql> create database test;
Query OK, 0 rows affected (0.24 sec)
创建完库以后在mycat的schemas目录下会有一个与该库名名的文件,要修该这个文件标注mycat的集群,然后重启mycat。
[root@bogon ~]# ll /usr/local/mycat/conf/schemas/总计 12-rw-r--r-- 1 root root 5299 2021年 9月29日 mysql.schema.json-rw-r--r-- 1 root root 143 6月 4日 20:34 test.schema.json[root@bogon ~]# vim /usr/local/mycat/conf/schemas/test.schema.json {"customTables":{},"globalTables":{},"normalProcedures":{},"normalTables":{},"schemaName":"test","targetName":"cls01","shardingTables":{},"views":{}}#重启mycat服务[root@bogon ~]# mycat restartmysql> create table test.zang(id int(10),name varchar(10),address varchar(10));Query OK, 0 rows affected (0.44 sec)
创建库和表的操作会随着路由到master执行,并同步到slave节点
停止 salve1 和 slave2 的主从同步
Slave1:
[root@localhost ~]# mysql -uroot -p
mysql> stop slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)
Slave2:
[root@localhost ~]# mysql -uroot -p
mysql> stop slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)
在 master 和 slave1、slave2 创建测试数据
Master 上操作
mysql> use test;
Database changed
mysql> insert into test.zang values ('1','zhang','this_is_master');
Query OK, 1 row affected (0.01 sec)
Slave1 上操作
mysql> use test;
Database changed
mysql> insert into test.zang values ('2','zhang','this_is_slavel');
Query OK, 1 row affected (0.01 sec)
Slave2 上操作
mysql> insert into test.zang values(4,'zhangsan','write_list');Query OK, 1 row affected (0.05 sec)#这是slave服务器的查询mysql> select * from zang;+------+----------+------------+| id | name | address |+------+----------+------------+| 4 | zhangsan | write_list |+------+----------+------------+1 row in set (0.00 sec)#这是master服务器的查询mysql> select * from test.zang;+------+----------+------------+| id | name | address |+------+----------+------------+| 4 | zhangsan | write_list || 5 | lisi | read_list |+------+----------+------------+2 rows in set (0.00 sec)
测试写操作
登录 mycat 集群执行写入操作
[root@localhost ~]# mysql -uroot -p123456 -P8066 -h192.168.10.101
MySQL [(none)]>insert into zang values('4','zhang','write_test');
Query OK,1 row affected (0.08 sec)
但在 slave1 和 slave2 上查询不到,最终只有在 Master 上才能查看到这条语句内容,说明写操作在 Master 服务器上。由此验证,已经实现了 MySQL 读写分离。目前所有的写操作都全部在 Master 主服务器上,用来避免数据的不同步;所有的读操作都分摊给了 Slave 从服务器,用来分担数据库压力。