目录
一、主从复制
1.1 主从复制简介
1.2 MySQL支持的复制类型
1.3 主从复制的工作过程
1.4 主从复制的同步模式
1.4.1 异步复制(Asynchronous replication)
1.4.2 全同步复制(Fully synchronous replication)
1.4.3 半同步复制(Semisynchronous replication)
范例1:新建主从复制
主节点操作:
从节点:
范例2:级联 主从复制
主节点:
2级节点:
从节点:
范例3:半同步复制
主节点:
从节点:
二、读写分离
2.1mycat实现读写分离
2.1.1 mycat安装目录结构说明
2.1.2 Mycat的常用配置文件
2.1.3 Mycat日志
2.2 mycat 实现读写分离实际操作
1.环境准备
2.初始化环境
3.部署主从复制
4.安装mycat(192.168.10.30)
5.修改 mycat 配置文件 /apps/mycat/conf/server.xml
6.修改 mycat 配置文件/apps/mycat/conf/schema.xml
详细解读:
7. 主服务器上授权
8.重启mycat服务,客户机连接mycat
9.客户端测试读写分离
三、 MHA实操
1关闭防火墙selinux
2.主节点(7-4)安装 管理和客户端工具
3.其余所有节点(7-1,7-2,7-3)安装客户端
4. 所有节点 基于key验证
5 主节点(7-4)建立mha文件夹和配置文件
6 准备切换脚本
7实现主从复制
7.1主服务器操作(7-1)
7.2从服务器设置(7-2,7-3)
7.2.1 服务器7-2配置
7.2.2服务器7-3配置
8.设置虚拟地址
9在运行前需要先检测环境是否符合
9.1 检测 ssh 免密登录是否成功
9.2 检测主从复制 是否可以
9.3 查看状态未开启
10 开启mha
11测试
11.1 mha 如何发现主节点宕机
11.2 查看 mha 服务的日志
11.3 模拟 mysql 主节点故障
一、主从复制
1.1 主从复制简介
MySQL主从复制是一种数据库复制技术,用于将一个MySQL数据库服务器的更改同步到其他MySQL数据库服务器。
在主从复制中,有一个主数据库(Master)和一个或多个从数据库(Slave)。
主数据库负责接收和处理所有的写操作,而从数据库则通过复制主数据库的日志文件,将这些写操作在自身的数据库中重演,从而实现数据的同步。
1.2 MySQL支持的复制类型
1)STATEMENT:基于语句的复制。在服务器上执行sql语句,在从服务器上执行同样的语句,mysql默认采用基于语句的复制,执行效率高;
2)ROW:基于行的复制。把改变的内容复制过去,而不是把命令在从服务器上执行一遍;
3)MIXED:混合类型的复制。默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。
1.3 主从复制的工作过程
主从复制原理:
1主节点负责用户的写操作,用户发起写操作后,会修改数据库
2.数据库修改后,会更新主节点上的二进制日志
3.主服务器会产生一个 dump线程, 一边读取二进制日志一边将二进制日志通过 网络传给从服务器
4.从服务器会开启io线程,接收主服务器的二进制日志
5 会写入中继日志,这时只是生成了一个文件,并没有同步
6.从服务器再开启 sql线程将 中继日志中 操作写入数据库完成更新
1.4 主从复制的同步模式
1.4.1 异步复制(Asynchronous replication)
一个主库,一个或多个从库,数据异步同步到从库。
MySQL默认的复制即是异步的。
主库在执行完客户端提交的事务后会立即将结果返给客户端,并不关心从库是否已经接收并处理。
这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。
1.4.2 全同步复制(Fully synchronous replication)
指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。
因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。
1.4.3 半同步复制(Semisynchronous replication)
在异步复制的基础上,确保任何一个主库上的事务在提交之前至少有一个从库已经收到该事务并记录。
介于异步复制和全同步复制之间。
主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端(只能保证主库的 Binlog 至少传输到了一个从节点上),否则需要等待直到超时时间然后切换成异步模式再提交。
相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。
所以,半同步复制最好在低延时的网络中使用。
范例1:新建主从复制
主节点:192.168.10.40
从节点:192.168.10.20
主节点操作:
[root@localhost ~]#vim /etc/my.cnf
#修改文件
[mysqld]
server_id=100
log-bin=/data/mysql-bin
[root@localhost ~]#mkdir /data/ -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld
select @@server_id;
#可以查看serverid 默认都是1
show master status;
#查看二进制日志位置
grant replication slave on *.* to test@'192.168.91.%' identified by 'Admin@123';
#建立复制用户
show processlist;
#查看线程
从节点:
[root@localhost ~]#vim /etc/my.cnf
#修改文件
[mysqld]
server_id=102
log-bin=/data/mysql-bin
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
#read-only #只读可加
[root@localhost ~]#mkdir /data/mysql/ -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld
CHANGE MASTER TO
MASTER_HOST='192.168.10.40',
MASTER_USER='test',
MASTER_PASSWORD='Admin@123',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=437;
show slave status\G;
#查看设置的状态
Seconds_Behind_Master: NULL #目前数据差
start slave;
#开启线程,开启主从复制
create database cxk;
#在主节点上建立数据测试
TIP:主从复制前的操作可以使用完全备份导入从节点中使主从一致
范例2:级联 主从复制
主节点:
root@localhost ~]#vim /etc/my.cnf
#修改文件
[mysqld]
server_id=100
log-bin=/data/mysql/mysql-bin
[root@localhost ~]#mkdir /data/mysql/ -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld
select @@server_id;
#可以查看serverid 默认都是1
show master status;
#查看二进制日志位置
grant replication slave on *.* to test@'192.168.10.%' identified by 'Admin@123';
#建立复制用户
show processlist;
#查看线程
2级节点:
root@localhost ~]#vim /etc/my.cnf
#修改文件
[mysqld]
server_id=101
log-bin=/data/mysql/mysql-bin
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
log_slave_updates
#read-only #只读可加
[root@localhost ~]#mkdir /data/mysql/ -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld
下面修改配置 命令较长可以使用帮助
help change master to
CHANGE MASTER TO
MASTER_HOST='192.168.10.40',
MASTER_USER='test',
MASTER_PASSWORD='Admin@123',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=604;
注意最后分号
show slave status\G;
#查看设置的状态
Seconds_Behind_Master: NULL #目前数据差
start slave;
#开启线程,开启主从复制
show master logs;
#查看 从节点的复制位置
从节点:
root@localhost ~]#vim /etc/my.cnf
#修改文件
[mysqld]
server_id=102
log-bin=/data/mysql/mysql-bin
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
#read-only #只读可加
[root@localhost ~]#mkdir /data/mysql/ -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld
下面修改配置 命令较长可以使用帮助
help change master to
CHANGE MASTER TO
MASTER_HOST='192.168.10.20',
MASTER_USER='test',
MASTER_PASSWORD='Admin@123',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=448;
注意最后分号
show slave status\G;
#查看设置的状态
Seconds_Behind_Master: NULL #目前数据差
start slave;
#开启线程,开启主从复制
范例3:半同步复制
实现:
rpm -ql mysql-community-server |grep semisync
#需要安装插件
主节点:
[root@localhost ~]#vim /etc/my.cnf
#修改文件
[mysqld]
server_id=100
log-bin=/data/mysql/mysql-bin
rpl_semi_sync_master_enabled=ON
rpl_semi_sync_master_timeout=3000
#修改此行,需要先安装semisync_master.so插件后,再重启,否则无法启动 开启半同步
#设置3s内无法同步,也将返回成功信息给客户端
[root@localhost ~]#mkdir /data/mysql/ -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld
[root@localhost ~]#mysql -uroot -pAdmin@123
mysql>INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; #永久安装插件
mysql>UNINSTALL PLUGIN rpl_semi_sync_master ;
mysql>rpm -ql mysql-community-server |grep semisync #查看插件
mysql>SET GLOBAL rpl_semi_sync_master_enabled=1; #临时修改变量
mysql>SET GLOBAL rpl_semi_sync_master_timeout = 3000; #超时长1s,默认值为10s
mysql>SHOW GLOBAL VARIABLES LIKE '%semi%';
#查看半同步状态
show global status like '%semi%';
#查看半同步客户端
show master status;
grant replication slave on *.* to test@'192.168.10.%' identified by 'Admin@123';
#建立复制用户
从节点:
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
#安装插件
[root@slave1 ~]#vim /etc/my.cnf
[mysqld]
server-id=101
rpl_semi_sync_slave_enabled=ON #修改此行,需要先安装semisync_slave.so插件后,再重启,否则无法启动
CHANGE MASTER TO
MASTER_HOST='192.168.10.40',
MASTER_USER='test',
MASTER_PASSWORD='Admin@123',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
注意最后分号
show global status like '%semi%';
#查看状态 主从状态
mysql>INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
mysql>SET GLOBAL rpl_semi_sync_slave_enabled=1; #临时修改变量
mysql> SHOW GLOBAL VARIABLES LIKE '%semi%';
二、读写分离
2.1mycat实现读写分离
2.1.1 mycat安装目录结构说明
-
bin :mycat命令,启动、重启、停止等运行目录
-
catlet: catlet为Mycat的一个扩展功能
-
conf :mycat 配置信息,重点关注
-
lib:mycat引用的jar包,Mycat是java开发的
-
logs :日志文件,包括Mycat启动的日志和运行的日志
-
version.txt :mycat版本说明
2.1.2 Mycat的常用配置文件
Mycat的配置文件都在conf目录里面,这里介绍几个常用的文件:
-
server.xml :Mycat软件本身相关的配置文件,设置账号、参数等
-
schema.xml:Mycat对应的物理数据库和数据库表的配置,读写分离、高可用、分布式策略定制、节点控制
-
rule.xml:Mycat分片(分库分表)规则配置文件,记录分片规则列表、使用方法等
2.1.3 Mycat日志
Mycat的日志文件都在logs目录里面
-
wrapper.log :mycat启动日志
-
mycat.log :mycat详细工作日志
2.2 mycat 实现读写分离实际操作
1.环境准备
mycat服务器上不能装mysql
master服务器 | 192.168.10.40 |
---|---|
slave1服务器 | 192.168.10.20 |
mycat服务器 | 192.168.10.30 |
客户机 | 192.168.10.10 |
2.初始化环境
#每台服务器上都初始化,关闭防火墙
systemctl stop --now firewalld
systemctl disable firewalld
setenforce 0
3.部署主从复制
###################### 主mysql服务器配置(192.168.10.40)########################
[root@localhost ~]#vim /etc/my.cnf
#修改文件
[mysqld]
server_id=100
log-bin=/data/mysql/mysql-bin
[root@localhost ~]#mkdir /data/mysql/ -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld
select @@server_id;
#可以查看serverid 默认都是1
show master status;
#查看二进制日志位置
grant replication slave on *.* to test@'192.168.10.%' identified by 'Admin@123';
#建立复制用户
show processlist;
#查看线程
############################# 从mysql服务器配置(192.168.10.20)################
[root@localhost ~]#vim /etc/my.cnf
#修改文件
[mysqld]
server_id=101
log-bin=/data/mysql/mysql-bin
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
#read only #只读可加
[root@localhost ~]#mkdir /data/mysql/ -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld
下面修改配置 命令较长可以使用帮助
help change master to
CHANGE MASTER TO
MASTER_HOST='192.168.10.40',
MASTER_USER='test',
MASTER_PASSWORD='Admin@123',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=448;
注意最后分号
show slave status\G;
#查看设置的状态
Seconds_Behind_Master: NULL #目前数据差
start slave;
#开启线程,开启主从复制
create database cxk;
#在主节点上建立数据测试
####################### 在master服务器上上传库文件,并在从服务器上验证主从同步 ############
#在主服务器上下载hellodb库文件,source后加绝对路径
[root@localhost ~]#mysql -uroot -pAdmin@123
#下载hellodb库文件
source /bak/hellodb.sql
show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| hellodb |
| mysql |
| performance_schema |
| sys |
+--------------------+
#在从库中查看库文件hellodb是否已经同步
show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| hellodb |
| mysql |
| performance_schema |
| sys |
+--------------------+
4.安装mycat(192.168.10.30)
(1)主机上安装java(mycat基于java)
#yum安装java
[root@localhost ~]#yum install java -y
#确认安装成功
[root@localhost ~]#java -version
openjdk version "1.8.0_131"
OpenJDK Runtime Environment (build 1.8.0_131-b12)
OpenJDK 64-Bit Server VM (build 25.131-b12, mixed mode)
(2)切换至opt目录,下载mycat安装包
[root@localhost ~]#cd /opt
[root@localhost ~]#wget http://dl.mycat.org.cn/1.6.7.6/20210303094759/Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz
(3)创建/apps文件夹,并解压mycat包至/apps下
[root@localhost ~]#mkdir /apps
[root@localhost ~]#tar zxvf Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz -C /apps/
(4)设置变量环境
[root@localhost ~]#echo 'PATH=/apps/mycat/bin:$PATH' > /etc/profile.d/mycat.sh
[root@localhost ~]#source /etc/profile.d/mycat.sh
(5)启动mycat,查看日志文件,最后可以看到启动成功
[root@localhost ~]#mycat start
#注意内存小于2G 起不来
Starting Mycat-server...
[root@localhost ~]#tail -f /apps/mycat/logs/wrapper.log
#启动成功日志末尾会出现successfully
STATUS | wrapper | 2021/12/09 21:04:10 | --> Wrapper Started as Daemon
STATUS | wrapper | 2021/12/09 21:04:10 | Launching a JVM...
INFO | jvm 1 | 2021/12/09 21:04:11 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
INFO | jvm 1 | 2021/12/09 21:04:11 | Copyright 1999-2006 Tanuki Software, Inc. All Rights Reserved.
INFO | jvm 1 | 2021/12/09 21:04:11 |
INFO | jvm 1 | 2021/12/09 21:04:12 | MyCAT Server startup successfully. see logs in logs/mycat.log
(6)客户端连接数据库
#这里密码初始为123456 需要加端口
[root@localhost bin]#mysql -uroot -p123456 -h 192.168.10.30 -P8066
5.修改 mycat 配置文件 /apps/mycat/conf/server.xml
[root@localhost ~]#vim /apps/mycat/conf/server.xml
#去掉44行行注释,对应的在51行行末注释,删除50行行末注释,5 * 60 * 1000L; //连接空> 闲检查
#修改45行端口号为3306
45 <property name="serverPort">3306</property>
#配置Mycat的连接信息(账号密码),在110 和111行, 可以修改,这边不修改了
####参数解释说明####
110 <user name="root" defaultAccount="true">
111 <property name="password">123456</property>
112 <property name="schemas">TESTDB</property>
113 <property name="defaultSchema">TESTDB</property>
116 <!-- 表级 DML 权限设置 -->
117 <!--
118 <privileges check="false">
119 <schema name="TESTDB" dml="0110" >
120 <table name="tb01" dml="0000"></table>
121 <table name="tb02" dml="1111"></table>
122 </schema>
123 </privileges>
124 -->
127 <user name="user">
128 <property name="password">user</property>
129 <property name="schemas">TESTDB</property>
130 <property name="readOnly">true</property>
131 <property name="defaultSchema">TESTDB</property>
user 用户配置节点
name 逻辑用户名,客户端登录MyCAT的用户名,也就是客户端用来连接Mycat的用户名。
password 客户端登录MyCAT的密码
schemas 数据库名,这里会和schema.xml中的配置关联,可配置多个,多个用逗号分开,例如:db1,db2
privileges 配置用户针对表的增删改查的权限
readOnly mycat 逻辑库所具有的权限。true为只读,false为读写都有,默认为false
##注意
1.#server.xml文件里登录mycat的用户名和密码可以任意定义,这个账号和密码是为客户机登录mycat时使用的账号信息
2.#逻辑库名(如上面的TESTDB,也就是登录mycat后显示的库名,切换这个库之后,显示的就是代理的真实mysql数据库的表)要在schema.xml里面也定义,否则会导致mycat服务启动失败!这里只定义了一个标签,所以把多余的都注释了。如果定义多个标签,即设置多个连接mycat的用户名和密码,那么就需要在schema.xml文件中定义多个对应的库!
6.修改 mycat 配置文件/apps/mycat/conf/schema.xml
schema.xml是最主要的配置项,此文件关联mysql读写分离策略,读写分离、分库分表策略、分片节点都是在此文件中配置的.MyCat作为中间件,它只是一个代理,本身并不进行数据存储,需要连接后端的MySQL物理服务器,此文件就是用来连接MySQL服务器的。
<?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="localhost1" database="hellodb" />
<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="host1" url="192.168.10.40:3306" user="root" password="Admin@123">
<readHost host="host2" url="192.168.10.20:3306" user="root" password="Admin@123"/>
</writeHost>
</dataHost>
</mycat:schema>
详细解读:
[root@localhost ~]#vim /apps/mycat/conf/schema.xml
#删除所有内容,重新写入以下
<?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标签:数据库设置,此数据库为逻辑数据库,name与server.xml中schema对应。
#name:逻辑数据库名,与server.xml中的schema对应;
#checkSQLschema: 数据库前缀相关设置,这里为false;
#sqlMaxLimit: select时默认的limit,避免查询全表,否则可能会遇到查询量特别大的情况造成卡 死;
#dataNode:表存储到哪些节点,多个节点用逗号分隔。节点为下文dataNode设置的name
</schema>
<dataNode name="dn1" dataHost="localhost1" database="hellodb" />
#dataNode标签: 定义mycat中的数据节点,也是通常说的数据分片,也就是分库相关配置
#name: 定义数据节点的名字,与table中dataNode对应
#datahost: 物理数据库名,与datahost中name对应,该属性用于定义该分片属于哪个数据库实例
#database: 物理数据库中数据库名,该属性用于定义该分片属性哪个具体数据库实例上的具体库
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
#dataHost标签: 物理数据库,真正存储数据的数据库
#name: 物理数据库名,与dataNode中dataHost对应
#maxCon属性指定每个读写实例连接池的最大连接。也就是说,标签内嵌套的writeHost、readHost标 签都会使用这个属性的值来实例化出连接池的最大连接数
#minCon属性指定每个读写实例连接池的最小连接,初始化连接池的大小
#balance: 均衡负载的方式
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
#writeType: 写入方式
#dbType: 数据库类型
#dbDriver指定连接后端数据库使用的 Driver,目前可选的值有 native 和 JDBC。用 native 的话,因为这个值执行的是二进制的 mysql 协议,所以可以使用 mysql 和maridb。其他类型的数据库则需要使用 JDBC 驱动来支持。
#switchType: “-1” 表示不自动切换; “1” 默认值,自动切换; “2” 基于 MySQL主从同步的状态决定是否切换心跳语句为 show slave status; “3” 基于 MySQL galary cluster 的切换机制(适合集群)(1.4.1)心跳语句为 show status like ‘wsrep%’.
<heartbeat>select user()</heartbeat>
#heartbeat: 心跳检测语句,注意语句结尾的分号要加
<writeHost host="host1" url="192.168.10.40:3306" user="root" password="Admin@123">
#host:用于标识不同实例,一般 writeHost 我们使用*M1,readHost 我们用*S1。
#url:后端实例连接地址。Native:地址:端口 JDBC:jdbc的url
#user:后端存储实例需要的用户名字
#password:后端存储实例需要的密码
<readHost host="host2" url="192.168.10.20:3306" user="root" password="Admin@123"/>
</writeHost>
</dataHost>
</mycat:schema>
#schema.xml文件中有三点需要注意:balance="1",writeType="0" ,switchType="1"
#schema.xml中的balance的取值决定了负载均衡对非事务内的读操作的处理。balance 属性负载均衡类型,目前的取值有 4 种:
##balance="0":不开启读写分离机制,所有读操作都发送到当前可用的writeHost上,即读请求仅 发送到writeHost上
##balance="1":一般用此模式,读请求随机分发到当前writeHost对应的readHost和standby的writeHost上。即全部的readHost与stand by writeHost 参与 select 语句的负载均衡,简单的说,当双主双从模式(M1 ->S1 , M2->S2,并且 M1 与 M2 互为主备),正常情况下, M2,S1, S2 都参与 select 语句的负载均衡
##balance="2":读请求随机分发到当前dataHost内所有的writeHost和readHost上。即所有读操作都随机的在writeHost、 readhost 上分发
##balance="3":读请求随机分发到当前writeHost对应的readHost上。即所有读请求随机的分发wiriterHost 对应的 readhost 执行, writerHost 不负担读压力,注意 balance=3 只在 1.4 及其以后版本有,1.3 没有
###writeHost和readHost标签,这两个标签都指定后端数据库的相关配置给mycat,用于实例化后端连接池。唯一不同的是:writeHost指定写实例、readHost指定读实例,组着这些读写实例来满足系统的要求。在一个dataHost内可以定义多个writeHost和eadHost。但是,如果writeHost指定的后端数据库宕机,那么这个writeHost绑定的所有readHost都将不可用。另一方面,由于这个writeHost宕机系统会自动的检测到,并切换到备用的writeHost上去
#PS:Mycat主从分离只是在读的时候做了处理,写入数据的时候,只会写入到writehost,需要通过mycat的主从复制将数据复制到readhost
7. 主服务器上授权
[root@localhost ~]#mysql -uroot -p123123
#授权
GRANT ALL ON *.* TO 'root'@'192.168.10.%' IDENTIFIED BY 'Admin@123';
#查看创建成功
use mysql;
select user,host from user;
8.重启mycat服务,客户机连接mycat
(1)在mycat服务器上,重启mycat服务,查看启动日志,文末出现successfully
[root@localhost ~]#mycat restart
[root@localhost ~]#tail -f /apps/mycat/logs/wrapper.log
INFO | jvm 1 | 2021/12/09 21:15:40 |
INFO | jvm 1 | 2021/12/09 21:15:40 | MyCAT Server startup successfully. see logs in logs/mycat.log
STATUS | wrapper | 2021/12/09 21:16:38 | TERM trapped. Shutting down.
STATUS | wrapper | 2021/12/09 21:16:39 | <-- Wrapper Stopped
STATUS | wrapper | 2021/12/09 21:16:40 | --> Wrapper Started as Daemon
STATUS | wrapper | 2021/12/09 21:16:40 | Launching a JVM...
INFO | jvm 1 | 2021/12/09 21:16:40 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
INFO | jvm 1 | 2021/12/09 21:16:40 | Copyright 1999-2006 Tanuki Software, Inc. All Rights Reserved.
INFO | jvm 1 | 2021/12/09 21:16:40 |
INFO | jvm 1 | 2021/12/09 21:16:41 | MyCAT Server startup successfully. see logs in logs/mycat.log
(2)查看3306端口,可以监听到主从服务器(192.168.10.40、192.168.10.20)
[root@localhost ~]# ss -antp|grep 3306
LISTEN 0 128 :::3306 :::* users:(("java",pid=74936,fd=185))
TIME-WAIT 0 0 ::ffff:192.168.10.40:37344 ::ffff:192.168.10.20:3306
ESTAB 0 0 ::ffff:192.168.10.40:58160 ::ffff:192.168.10.20:3306 users:(("java",pid=74936,fd=195))
(3)在客户机上登录mycat,这时可以不加端口直接进入数据库了
[root@localhost ~]#mysql -uroot -p123456 -h 192.168.10.30
#看是否能查到表
create table student (id smallint unsigned primary key auto_increment, name varchar(10), age tinyint unsigned,gender enum('M','F') default 'M' );
show databases;
use TESTDB;
show tables;
+-------------------+
| Tables_in_hellodb |
+-------------------+
| classes |
| coc |
| courses |
| scores |
| students |
| teachers |
| toc |
+-------------------+
#查看当前的查询来自哪台服务器,可以看到查询功能来自id为2的从服务器
select @@server_id;
+-------------+
| @@server_id |
+-------------+
| 2 |
+-------------+
9.客户端测试读写分离
(1)在主从服务器上都打开通用日志
[root@localhost ~]#mysql -uroot -p123123
#打开通用日志
set global general_log=1;
#查看通用查询日志是否开启
show variables like 'general%';
+------------------+-------------------------------------+
| Variable_name | Value |
+------------------+-------------------------------------+
| general_log | ON |
| general_log_file | /usr/local/mysql/data/localhost.log |
+------------------+-------------------------------------+
set global general_log=1;
show variables like 'general%';
(2)在主从服务器上实时查看通用日志
[root@localhost ~]#tail -f /usr/local/mysql/data/localhost.log
(3)在客户机上的表中插入数据,并查看主从服务器实时日志,可以看到只有主服务器上有日志变化显示
[root@localhost ~]#mysql -uroot -p123456 -h 192.168.10.30
insert into teachers values(5,'Xiao Ming',46,'F');
(4)在客户机上select查表,并查看主从服务器实时日志,可以看到只有从服务器上有日志变化显示,从而实现了读写分离
select * from teachers;
三、 MHA实操
机器 | 作用 |
---|---|
7-4 192.168.10.10 | MHA管理节点 |
7-1 192.168.10.40 | 主 |
7-2 192.168.10.20 | 从 |
7-3 192.168.10.30 | 从 |
准备文件
7-4 需要客户端和服务端,其余只需要客户端
1关闭防火墙selinux
systemctl disable --now firewalld
setenforce 0
2.主节点(7-4)安装 管理和客户端工具
[root@localhost opt]#yum install epel-release.noarch -y
#有依赖性用yum安装 需要先安装 epel源
[root@localhost data]#ls
mha4mysql-manager-0.58-0.el7.centos.noarch.rpm mha4mysql-node-0.58-0.el7.centos.noarch.rpm
[root@localhost opt]#yum -y install mha4mysql-*.rpm
3.其余所有节点(7-1,7-2,7-3)安装客户端
[root@localhost opt]#yum install epel-release.noarch -y
[root@localhost data]# yum install mha4mysql-node-0.58-0.el7.centos.noarch.rpm -y
4. 所有节点 基于key验证
[root@localhost data]#ssh-keygen
[root@localhost data]#ssh-copy-id 127.0.0.1
#自己和自己连生成 秘钥
[root@localhost data]#cd
[root@localhost data]#rsync -a .ssh 192.168.10.20:/root/
[root@localhost data]#rsync -a .ssh 192.168.10.20:/root/
[root@localhost data]#rsync -a .ssh 192.168.10.30:/root/
#注意.ssh 后不能加/ -a 保留属性
5 主节点(7-4)建立mha文件夹和配置文件
[root@localhost ~]#mkdir /etc/mastermha
[root@localhost ~]#vim /etc/mastermha/app1.cnf
[server default]
user=mhauser
password=Admin@123
manager_workdir=/data/mastermha/app1/
manager_log=/data/mastermha/app1/manager.log
remote_workdir=/data/mastermha/app1/
ssh_user=root
repl_user=test
repl_password=Admin@123
ping_interval=1
master_ip_failover_script=/usr/local/bin/master_ip_failover
check_repl_delay=0
master_binlog_dir=/data/mysql/
[server1]
hostname=192.168.10.40
candidate_master=1
[server2]
hostname=192.168.10.20
candidate_master=1
[server3]
hostname=192.168.10.30
6 准备切换脚本
[root@localhost ~]#vim master_ip_failover
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
my (
$command, $ssh_user, $orig_master_host, $orig_master_ip,
$orig_master_port, $new_master_host, $new_master_ip, $new_master_port
);
my $vip = '192.168.10.188/24';
my $gateway = '192.168.10.2';
my $interface = 'ens33';
my $key = "1";
my $ssh_start_vip = "/sbin/ifconfig $interface:$key $vip;/sbin/arping -I $interface -c 3 -s $vip $gateway >/dev/null 2>&1";
my $ssh_stop_vip = "/sbin/ifconfig $interface:$key down";
GetOptions(
'command=s' => \$command,
'ssh_user=s' => \$ssh_user,
'orig_master_host=s' => \$orig_master_host,
'orig_master_ip=s' => \$orig_master_ip,
'orig_master_port=i' => \$orig_master_port,
'new_master_host=s' => \$new_master_host,
'new_master_ip=s' => \$new_master_ip,
'new_master_port=i' => \$new_master_port,
);
exit &main();
sub main {
print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";
if ( $command eq "stop" || $command eq "stopssh" ) {
# $orig_master_host, $orig_master_ip, $orig_master_port are passed.
# If you manage master ip address at global catalog database,
# invalidate orig_master_ip here.
my $exit_code = 1;
eval {
print "Disabling the VIP on old master: $orig_master_host \n";
&stop_vip();
$exit_code = 0;
};
if ($@) {
warn "Got Error: $@\n";
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "start" ) {
# all arguments are passed.
# If you manage master ip address at global catalog database,
# activate new_master_ip here.
# You can also grant write access (create user, set read_only=0, etc) here.
my $exit_code = 10;
eval {
print "Enabling the VIP - $vip on the new master - $new_master_host \n";
&start_vip();
$exit_code = 0;
};
if ($@) {
warn $@;
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {
print "Checking the Status of the script.. OK \n";
`ssh $ssh_user\@$orig_master_host \" $ssh_start_vip \"`;
exit 0;
}
else {
&usage();
exit 1;
}
}
# A simple system call that enable the VIP on the new master
sub start_vip() {
`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
# A simple system call that disable the VIP on the old_master
sub stop_vip() {
`ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}
sub usage {
print
"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}
[root@localhost ~]#cp master_ip_failover /usr/local/bin/
# 移动文件到对应的地方 之前的配置文件中规定了地方
[root@localhost ~]#chmod +x /usr/local/bin/master_ip_failover
#加上执行权限
7实现主从复制
7.1主服务器操作(7-1)
[root@localhost ~]#vim /etc/my.cnf
#修改文件
[mysqld]
server_id=100
log-bin=/data/mysql/mysql-bin
skip_name_resolve=1
general_log
#通用日志
[root@localhost data]#mysql -uroot -pabc123
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
mysql> grant replication slave on *.* to test@'192.168.10.%' identified by 'Admin@123';
#建立复制用户
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> grant all on *.* to mhauser@'192.168.10.%' identified by 'Admin@123';
#建立 mha管理账户
Query OK, 0 rows affected, 1 warning (0.00 sec)
7.2从服务器设置(7-2,7-3)
7.2.1 服务器7-2配置
[root@localhost ~]#vim /etc/my.cnf
#修改文件
server_id=101
log-bin=/data/mysql/mysql-bin
read_only
relay_log_purge=0
skip_name_resolve=1
general_log
[root@localhost ~]#mkdir /data/mysql/ -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld
[root@localhost data]#mysql -uroot -pabc123
CHANGE MASTER TO
MASTER_HOST='192.168.10.40',
MASTER_USER='test',
MASTER_PASSWORD='Admin@123',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
注意最后分号
mysql> start slave;
mysql> show slave status\G;
7.2.2服务器7-3配置
[root@localhost ~]#vim /etc/my.cnf
#修改文件
server_id=102
log-bin=/data/mysql/mysql-bin
read_only
relay_log_purge=0
skip_name_resolve=1
general_log
[root@localhost ~]#mkdir /data/mysql/ -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld
[root@localhost data]#mysql -uroot -pabc123
CHANGE MASTER TO
MASTER_HOST='192.168.10.40f',
MASTER_USER='test',
MASTER_PASSWORD='Admin@123',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
注意最后分号
mysql> start slave;
mysql> show slave status\G;
8.设置虚拟地址
在 mysql 主节点上配置 虚拟地址 也就是7-1
[root@localhost ~]#ifconfig ens33:1 192.168.10.188/24
9在运行前需要先检测环境是否符合
在管理节点 7-3 上执行
9.1 检测 ssh 免密登录是否成功
[root@localhost ~]#masterha_check_ssh --conf=/etc/mastermha/app1.cnf
Thu Jul 4 23:55:53 2024 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Thu Jul 4 23:55:53 2024 - [info] Reading application default configuration from /etc/mastermha/app1.cnf..
Thu Jul 4 23:55:53 2024 - [info] Reading server configuration from /etc/mastermha/app1.cnf..
Thu Jul 4 23:55:53 2024 - [info] Starting SSH connection tests..
Thu Jul 4 23:55:55 2024 - [debug]
Thu Jul 4 23:55:53 2024 - [debug] Connecting via SSH from root@192.168.10.40(192.168.10.40:22) to root@192.168.10.20(192.168.10.20:22)..
Thu Jul 4 23:55:54 2024 - [debug] ok.
Thu Jul 4 23:55:54 2024 - [debug] Connecting via SSH from root@192.168.10.40(192.168.10.40:22) to root@192.168.10.30(192.168.10.30:22)..
Thu Jul 4 23:55:55 2024 - [debug] ok.
Thu Jul 4 23:55:56 2024 - [debug]
Thu Jul 4 23:55:54 2024 - [debug] Connecting via SSH from root@192.168.10.30(192.168.10.30:22) to root@192.168.10.40(192.168.10.40:22)..
Thu Jul 4 23:55:55 2024 - [debug] ok.
Thu Jul 4 23:55:55 2024 - [debug] Connecting via SSH from root@192.168.10.30(192.168.10.30:22) to root@192.168.10.20(192.168.10.20:22)..
Thu Jul 4 23:55:56 2024 - [debug] ok.
Thu Jul 4 23:55:56 2024 - [debug]
Thu Jul 4 23:55:54 2024 - [debug] Connecting via SSH from root@192.168.10.20(192.168.10.20:22) to root@192.168.10.40(192.168.10.40:22)..
Thu Jul 4 23:55:55 2024 - [debug] ok.
Thu Jul 4 23:55:55 2024 - [debug] Connecting via SSH from root@192.168.10.20(192.168.10.20:22) to root@192.168.10.30(192.168.10.30:22)..
Thu Jul 4 23:55:55 2024 - [debug] ok.
Thu Jul 4 23:55:56 2024 - [info] All SSH connection tests passed successfully.
9.2 检测主从复制 是否可以
[root@localhost /]#masterha_check_repl --conf=/etc/mastermha/app1.cnf
# --conf=/etc/mastermha/app1.cnf 指明配置文件
.........................................................
.........................................................
.........................................................
Checking the Status of the script.. OK
Fri Jul 5 00:03:44 2024 - [info] OK.
Fri Jul 5 00:03:44 2024 - [warning] shutdown_script is not defined.
Fri Jul 5 00:03:44 2024 - [info] Got exit code 0 (Not master dead).
MySQL Replication Health is OK.
9.3 查看状态未开启
[root@localhost /]#masterha_check_status --conf=/etc/mastermha/app1.cnf
app1 is stopped(2:NOT_RUNNING).
10 开启mha
#开启MHA,默认是前台运行,生产环境一般为后台执行
nohup masterha_manager --conf=/etc/mastermha/app1.cnf &> /dev/null
#非后台
masterha_manager --conf=/etc/mastermha/app1.cnf
#查看状态
masterha_check_status --conf=/etc/mastermha/app1.cnf
11测试
11.1 mha 如何发现主节点宕机
通过发送 SELECT 1 As Value 指令 把1 设置成 value 给主, 主无法执行就认为他死了
[root@localhost mysql]#tail -f /var/lib/mysql/localhost.log
2024-07-04T16:11:14.137683Z 9 Query SELECT 1 As Value
2024-07-04T16:11:15.137991Z 9 Query SELECT 1 As Value
2024-07-04T16:11:16.137965Z 9 Query SELECT 1 As Value
2024-07-04T16:11:17.138401Z 9 Query SELECT 1 As Value
2024-07-04T16:11:18.138703Z 9 Query SELECT 1 As Value
2024-07-04T16:11:19.138877Z 9 Query SELECT 1 As Value
2024-07-04T16:11:20.139094Z 9 Query SELECT 1 As Value
2024-07-04T16:11:21.139400Z 9 Query SELECT 1 As Value
2024-07-04T16:11:22.140600Z 9 Query SELECT 1 As Value
2024-07-04T16:11:23.140507Z 9 Query SELECT 1 As Value
2024-07-04T16:11:24.141510Z 9 Query SELECT 1 As Value
2024-07-04T16:11:25.141256Z 9 Query SELECT 1 As Value
11.2 查看 mha 服务的日志
[root@localhost ~]#tail -f /data/mastermha/app1/manager.log
IN SCRIPT TEST====/sbin/ifconfig ens33:1 down==/sbin/ifconfig ens33:1 192.168.10.188/24;/sbin/arping -I ens33 -c 3 -s 192.168.10.188/24 192.168.10.2 >/dev/null 2>&1===
Checking the Status of the script.. OK
Fri Jul 5 00:08:27 2024 - [info] OK.
Fri Jul 5 00:08:27 2024 - [warning] shutdown_script is not defined.
Fri Jul 5 00:08:27 2024 - [info] Set master ping interval 1 seconds.
Fri Jul 5 00:08:27 2024 - [warning] secondary_check_script is not defined. It is highly recommended setting it to check master reachability from two or more routes.
Fri Jul 5 00:08:27 2024 - [info] Starting ping health check on 192.168.10.40(192.168.10.40:3306)..
## Fri Jul 5 00:08:27 2024 - [info] Ping(SELECT) succeeded, waiting until MySQL doesn't respond..
11.3 模拟 mysql 主节点故障
关闭主mysql服务器
systemctl stop mysqld
在从节点 102 上查看slave 信息 可以看到指向 新的主
```
mysql> show slave status\G;
```
查看日志
[root@localhost ~]#tail -f /data/mastermha/app1/manager.log
----- Failover Report -----
app1: MySQL Master failover 192.168.10.40(192.168.10.40:3306) to 192.168.10.20(192.168.10.20:3306) succeeded
Master 192.168.10.40(192.168.10.40:3306) is down!
Check MHA Manager logs at localhost.localdomain:/data/mastermha/app1/manager.log for details.
Started automated(non-interactive) failover.
Invalidated master IP address on 192.168.10.40(192.168.10.40:3306)
The latest slave 192.168.10.20(192.168.10.20:3306) has all relay logs for recovery.
Selected 192.168.10.20(192.168.10.20:3306) as a new master.
192.168.10.20(192.168.10.20:3306): OK: Applying all logs succeeded.
192.168.10.20(192.168.10.20:3306): OK: Activated master IP address.
192.168.10.30(192.168.10.30:3306): This host has the latest relay log events.
Generating relay diff files from the latest slave succeeded.
192.168.10.30(192.168.10.30:3306): OK: Applying all logs succeeded. Slave started, replicating from 192.168.10.20(192.168.10.20:3306)
192.168.10.20(192.168.10.20:3306): Resetting slave info succeeded.
# Master failover to 192.168.10.20(192.168.10.20:3306) completed successfully.
并且虚拟ip也在101 服务器上出现
[root@node2 ~]#ifconfig