通过keepalived搭建MySQL双主模式的MySQL集群
高可用MySQL的整体解决方案、体系化原理和指导思路https://coffeemilk.blog.csdn.net/article/details/152078348
一、MySQL双主互备模式架构和环境
1.1、MySQL主主互备模式架构
| |
MySQL主主互备模式架构的主要设计思路是: 通过MySQL Replication技术将两台MySQL Server互相将对方作为自己的Master,自己又同时作为对方的Slave来进行复制。这样就实现了高可用构架中的数据同步功能,同时,将采用KeepAlived来实现Mysql的自动故障恢复(failover)。在这个构架中,虽然两台MySQL Server互为主从,但同一时刻只有一个MySQL Server可读写,另一个MySQL Server只能进行读操作,这样可保证数据的一致性。 |
1.2、MySQL主主互备环境
序号 | MySQL主主互备环境说明 |
1 | 两台物理机或虚拟机,使用OpenEuler2203LTS或(RHEL9/Almalinux9.1)及其更高系统 |
2 | MySQL版本为:8.0.43 |
3 | keepalived版本为:2.3.4 |
4 | 两台主机的IP规划:192.168.1.10(DB1)、192.168.1.40(DB2) 配置Linux的网络为静态IP地址的一些方法 修改Linux上的ssh的默认端口号——及其客户端使用ssh连接不上Linux问题排查解决 |
#查看Linux系统版本信息命令
uname -r
cat /etc/os-release
1.3、MySQL安装
全网最全的关系型数据库MySQL解析及其安装部署的保姆级教程https://blog.csdn.net/xiaochenXIHUA/article/details/151891095?spm=1001.2014.3001.5501关系数据库MySQL的常用基础命令详解实战
https://coffeemilk.blog.csdn.net/article/details/151959864
我们这里直接从MySQL官网下载mysql-8.0.43的64位二进制包来进行安装:
#使用MySQL二进制包安装的详细实操流程#1-下载MySQL二进制安装包并解压
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.43-linux-glibc2.28-x86_64.tar.xz -c 0 -P /data
mkdir -p /usr/local/mysql
cd /data
tar -xvf mysql-8.0.43-linux-glibc2.28-x86_64.tar.xz -C /usr/local/mysql/#2-进入mysql的安装目录修改名称
cd /usr/local/mysql/
mv mysql-8.0.43-linux-glibc2.28-x86_64 mysql-8.0.43#3-创建mysql用户且给mysql二进制文件所在目录【/usr/local/mysql/mysql-8.0.43/】创建data、etc、logs文件夹
useradd mysql
id mysql
cd mysql-8.0.43/
mkdir -p /usr/local/mysql/mysql-8.0.43/{data,etc,logs}
cd etc#4-进入【/usr/local/mysql/mysql-8.0.43/etc】下创建并编辑mysql的配置文件my.cnf及其配置里面的内容
cd /usr/local/mysql/mysql-8.0.43/etc
vi my.cnf[mysqld]
#指定mysql的数据存放路径
datadir=/usr/local/mysql/mysql-8.0.43/data
socket=/tmp/mysql.sock
#指定mysql的报错日志文件
log-error=/usr/local/mysql/mysql-8.0.43/logs/mysqld-error.log
pid-file=/usr/local/mysql/mysql-8.0.43/logs/mysqld.pid
port=13336
user=mysql
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
#默认时区(东八区)
default-time-zone='+8:00'
#数据库日志时间匹配系统时区
log_timestamps=system
#表名和字段名不区分大小写
lower_case_table_names=1#5-将mysql文件夹及其内容都授权给mysql用户并初始化(注意:初始化后没有任何信息提示表示初始化成功,否则就是有问题的)
chown -R mysql:mysql /usr/local/mysql
/usr/local/mysql/mysql-8.0.43/bin/mysqld --defaults-file=/usr/local/mysql/mysql-8.0.43/etc/my.cnf --initialize --user=mysql#6-查看日志文件获取临时密码(复制一份临时密码用于登录和修改密码)
cd /usr/local/mysql/mysql-8.0.43/logs/
tail -f mysqld-error.log#7-手动启用mysql服务测试(如可以指定默认的配置文件【 --defaults-file=/usr/local/mysql/mysql-8.0.43/etc/my.cnf】)【查看mysql的进程、网络端口内容(查看到对应的mysql进程与网络端口与我们配置的一致表示正常;然后使用临时密码登录到mysql服务器中修改root用户密码;最后确认正常后即可杀死该进程)】
/usr/local/mysql/mysql-8.0.43/bin/mysqld_safe --defaults-file=/usr/local/mysql/mysql-8.0.43/etc/my.cnf
ps -ef | grep mysql
netstat -antlp | grep mysql
/usr/local/mysql/mysql-8.0.43/bin/mysql -uroot -p'临时密码'
alter user 'root'@'localhost' identified by 'abc123456';
flush privileges;#8-配置mysql的服务
vi /etc/systemd/system/mysqld.service[Unit]
Description=MySQL Server 8.0.43
After=network.target[Service]
User=mysql
Group=mysql
ExecStart=/usr/local/mysql/mysql-8.0.43/bin/mysqld_safe --defaults-file=/usr/local/mysql/mysql-8.0.43/etc/my.cnf
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID
Restart=on-failure[Install]
WantedBy=multi-user.target#9-启动mysql服务并设置开机自启
#9.1-重载所有服务
systemctl daemon-reload#9.2-启动mysql服务
systemctl start mysqld.service#9.3-查看mysql服务状态
systemctl status mysqld.service#9.4-设置mysql服务开机自启
systemctl enable mysqld.service #9.5-停止mysql服务
systemctl stop mysqld.service#10-可以重启Linux后查看mysql服务状态看它是否开机重启
reboot now
systemctl status mysqld.service
#对外放开mysql的指定端口号
firewall-cmd --zone=public --add-port=13336/tcp --permanent
firewall-cmd --reload
firewall-cmd --list-port
Linux中实现可执行文件或脚本在全局可用https://blog.csdn.net/xiaochenXIHUA/article/details/151955875?spm=1001.2014.3001.5501 注意:我们在安装好一台服务器的mysql后,若不想在另一台服务器上重新安装,则可以先把当前这台安装好的服务器的mysql先停止;然后将【/usr/local/mysql/mysql-8.0.43】整个文件夹压缩一份,然后将压缩好的内容传输到另一台服务器上解压即可(注意:若两个服务器的mysql数据库是直接拷贝而来,需要修改任意一个库的UUID,UUID在mysql的data目录下对应的auto.cnf文件中。两个库的UUID不能相同)。
cd /usr/local/mysql
tar zcvf mysql-8.0.43.tar.gz mysql-8.0.43
scp -P 22222 mysql-8.0.43.tar.gz root@192.168.1.40:/usr/local/mysql
二、实现MySQL主主互备模式
第十七章复制_MySQL 8.0 参考手册https://mysql.net.cn/doc/refman/8.0/en/replication.html
2.1、修改MySQL的配置文件实现主主互备基础
序号 | MySQL配置文件实现 主主互备的参数项 | 说明 |
1 | gtid_mode | 开启GTID(全局事务标识符),简化复制的管理和故障恢复。 |
2 | enforce_gtid_consistency | 强制所有事务都兼容GTID,确保复制的正确性。 |
3 | server-id | 是节点标识,主、从节点不能相同,必须全局唯一 |
4 | log-bin | 表示开启MySQL的binlog日志功能。 “mysql-bin”表示日志文件的命名格式,会生成文件名为mysql-bin.000001、mysql-bin.000002等的日志文件。 |
5 | relay-log | 定义relay-log日志文件的命名格式。 |
6 | replicate-wild-ignore-table | 复制过滤选项,可以过滤掉不需要复制的数据库或表,例如“mysql.%“表示不复制mysql库下的所有对象,其他依此类推。 |
7 | replicate_wild_do_table | 用来指定需要复制的数据库或表。 |
8 | log_replica_updates | 开启日志的复制更新操作 |
9 | plugin_load | 作用是在服务器启动时加载指定的插件库文件。通过这个选项,可以确保某些插件在 MySQL 服务启动时自动加载,而无需在运行时手动加载。 |
10 | rpl_semi_sync_source_enabled | 是 MySQL 半同步复制中的一个关键系统变量,用于控制是否在【主库】上启用半同步复制功能(0表示不开启,1表示开启)【当启用时,主库会在事务提交时等待至少一个副本确认接收到事务,从而保证数据的可靠性】。 它是从 MySQL 8.0.26 开始引入的新术语,替代了旧版本中的 rpl_semi_sync_master_enabled |
11 | rpl_semi_sync_replica_enabled | 是 MySQL 半同步复制中的一个关键系统变量,用于控制是否在【从库】上启用半同步复制功能(0表示不开启,1表示开启) 它是从 MySQL 8.0.26 开始引入的新术语,替代了旧版本中的 rpl_semi_sync_slave_enabled |
注意: 《1》不要在主库上使用【binlog-do-db】或【binlog-ignore-db】选项; 《2》也不要在从库上使用【replicate-do-db】或【replicate-ignore-db】选项;因为这样可能产生跨库更新失败的问题。 《3》推荐在从库上使用【replicate_wild_do_table】和【replicate-wild-ignore-table】两个选项来解决复制过滤问题。 | ||
【mysql_native_password】的作用是启用或指定 MySQL 使用传统的 mysql_native_password 认证插件。 这个插件是 MySQL 8.0 之前版本的默认认证方式,而在 MySQL 8.0 及以上版本中,默认的认证插件改为 caching_sha2_password |
《1》修改DB1主机(192.168.1.10)的配置文件【/usr/local/mysql/mysql-8.0.43/etc/my.cnf】实现MySQL主主互备的完整参数内容:
#实现MySQL主主互备的DB1(192.168.1.10)配置文件【/usr/local/mysql/mysql-8.0.43/etc/my.cnf】完整内容[mysqld]
#指定mysql的数据存放路径
datadir=/usr/local/mysql/mysql-8.0.43/data
socket=/tmp/mysql.sock
#指定mysql的报错日志文件
log-error=/usr/local/mysql/mysql-8.0.43/logs/mysqld-error.log
pid-file=/usr/local/mysql/mysql-8.0.43/logs/mysqld.pid
port=13336
user=mysql
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
#默认时区(东八区)
default-time-zone='+8:00'
#数据库日志时间匹配系统时区
log_timestamps=system
#表名和字段名不区分大小写
lower_case_table_names=1
#如下是主主互备的配置参数
gtid_mode=ON
enforce_gtid_consistency=ON
server-id = 1
log-bin=mysql-bin
relay-log = mysql-relay-bin
replicate-wild-ignore-table=mysql.%
replicate-wild-ignore-table=test.%
replicate-wild-ignore-table=information_schema.%
plugin_load = "rpl_semi_sync_source=semisync_source.so;rpl_semi_sync_replica=semisync_replica.so"
rpl_semi_sync_source_enabled=1
rpl_semi_sync_replica_enabled=1
log_replica_updates=ON
《2》修改DB2主机(192.168.1.40)的配置文件【/usr/local/mysql/mysql-8.0.43/etc/my.cnf】实现MySQL主主互备的完整参数内容:
#实现MySQL主主互备的DB1(192.168.1.40)配置文件【/usr/local/mysql/mysql-8.0.43/etc/my.cnf】完整内容
[mysqld]
#指定mysql的数据存放路径
datadir=/usr/local/mysql/mysql-8.0.43/data
socket=/tmp/mysql.sock
#指定mysql的报错日志文件
log-error=/usr/local/mysql/mysql-8.0.43/logs/mysqld-error.log
pid-file=/usr/local/mysql/mysql-8.0.43/logs/mysqld.pid
port=13336
user=mysql
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
#默认时区(东八区)
default-time-zone='+8:00'
#数据库日志时间匹配系统时区
log_timestamps=system
#表名和字段名不区分大小写
lower_case_table_names=1
#如下是主主互备的配置参数
gtid_mode=ON
enforce_gtid_consistency=ON
server-id = 2
log-bin=mysql-bin
relay-log = mysql-relay-bin
replicate-wild-ignore-table=mysql.%
replicate-wild-ignore-table=test.%
replicate-wild-ignore-table=information_schema.%
plugin_load = "rpl_semi_sync_source=semisync_source.so;rpl_semi_sync_replica=semisync_replica.so"
rpl_semi_sync_source_enabled=1
rpl_semi_sync_replica_enabled=1
log_replica_updates=ON
两台服务器上的MySQL主主互备的配置文件都修改完成保存退出后就可以重启MySQL服务了。
ps -ef | grep mysql
sytemctl restart mysqld
systemctl status mysqld.service
ps -ef | grep mysql
2.2、实现主主互备的MySQL操作
2.2.1、实现DB2指定DB1为主服务
#在DB1(192.168.1.10)的mysql库中创建复制用户
/usr/local/mysql/mysql-8.0.43/bin/mysql -uroot -pcreate user 'repl_user'@'192.168.1.%' identified with mysql_native_password by 'repl_passwd';GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl_user'@'192.168.1.%';FLUSH PRIVILEGES;
#在DB2(192.168.1.40)的mysql库中将DB1(192.168.1.10)设为自己的主服务器:
/usr/local/mysql/mysql-8.0.43/bin/mysql -uroot -pCHANGE REPLICATION SOURCE TO
SOURCE_HOST = '192.168.1.10',
SOURCE_PORT = 13336,
SOURCE_USER = 'repl_user',
SOURCE_PASSWORD = 'repl_passwd',
SOURCE_AUTO_POSITION = 1;#接着就可以在DB2的mysql上启动slave服务和查看slave的状态了,可执行如下SQL命令(我们的mysql版本是:8.0.43大于8.0.22,因此执行如下命令):
stop replica;
start replica;
show replica status\G;#mysql是8.0.22之前就执行如下命令
stop slave;
start slave;
show slave status\G;
在DB2上mysql查看slave的运行状态,如果看出Replica_IO_Running和Replica_SQL_Running都是Yes状态,表明DB2上复制服务运行正常【即从DB1到DB2的mysql主从复制已经完成了】。
2.2.2、实现DB1指定DB2为主服务
#在DB2(192.168.1.40)的mysql库中创建复制用户
/usr/local/mysql/mysql-8.0.43/bin/mysql -uroot -pcreate user 'repl_user'@'192.168.1.%' identified with mysql_native_password by 'repl_passwd';GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl_user'@'192.168.1.%';FLUSH PRIVILEGES;
#在DB1(192.168.1.10)的mysql库中将DB2(192.168.1.40)设为自己的主服务器:
/usr/local/mysql/mysql-8.0.43/bin/mysql -uroot -pCHANGE REPLICATION SOURCE TO
SOURCE_HOST = '192.168.1.40',
SOURCE_PORT = 13336,
SOURCE_USER = 'repl_user',
SOURCE_PASSWORD = 'repl_passwd',
SOURCE_AUTO_POSITION = 1;#接着就可以在DB2的mysql上启动slave服务和查看slave的状态了,可执行如下SQL命令(我们的mysql版本是:8.0.43大于8.0.22,因此执行如下命令):
stop replica;
start replica;
show replica status\G;#mysql是8.0.22之前就执行如下命令
stop slave;
start slave;
show slave status\G;
在DB1上mysql查看slave的运行状态,如果看出Replica_IO_Running和Replica_SQL_Running都是Yes状态,表明DB1上复制服务运行正常【即从DB2到DB1的mysql主从复制已经完成了】。
三、配置keepalived实现MySQL双主高可用
3.1、在DB1配置keepalived主节点
从零到一使用开源Keepalived配置实现高可用的集群教程https://coffeemilk.blog.csdn.net/article/details/151720348
#安装配置keepalived实现MySQL双主高可用流程#1-使用yum在线安装keepalived
yum install keepalived -y#2-进入keepalived的配置文件路径进行配置
cd /etc/keepalived/
cp -p keepalived.conf keepalived.conf.sample
vi keepalived.conf#2.1-【/etc/keepalived/keepalived.conf】文件的详细内容如下:! Configuration File for keepalivedglobal_defs {notification_email {ck@163.comck@qq.com }notification_email_from ckDB1smtp_server 192.168.1.100smtp_connect_timeout 30router_id MYSQL_DEVEL
}vrrp_script check_mysqld {script "/etc/keepalived/check_slave.pl 127.0.0.1"interval 2
}vrrp_instance VI_1 {state MASTERinterface ens33virtual_router_id 51priority 100advert_int 1authentication {auth_type PASSauth_pass qwer1234}track_script {check_mysqld}virtual_ipaddress {192.168.1.227/24 dev ens33}
}#3-编辑mysql的检测脚本【/etc/keepalived/check_slave.pl】
vi check_slave.pl
chmod 755 check_slave.pl
#3.1-【check_slave.pl】脚本编辑完成后可以在Linux中进行测试(若结果返回0则表示mysql是正常运行中,否则就是异常的)
yum install perl-DBI perl-DBD-mysql -y
./check_slave.pl 127.0.0.1
echo $?
#【/etc/keepalived/check_slave.pl】文件的详细内容如下:#!/usr/bin/perl -wuse DBI;use DBD::mysql;# CONFIG VARIABLES$SBM = 120;$db = "mysql";$host = $ARGV[0];$port = 13336;$user = "root";$pw = "abc123456";# SQL query$query = "show slave status";$dbh = DBI->connect("DBI:mysql:$db:$host:$port", $user, $pw, { RaiseError => 0,PrintError => 0 });if (!defined($dbh)) {exit 1;}$sqlQuery = $dbh->prepare($query);$sqlQuery->execute;$Slave_IO_Running = "";$Slave_SQL_Running = "";$Seconds_Behind_Master = "";while (my $ref = $sqlQuery->fetchrow_hashref()) {$Slave_IO_Running = $ref->{'Slave_IO_Running'};$Slave_SQL_Running = $ref->{'Slave_SQL_Running'};$Seconds_Behind_Master = $ref->{'Seconds_Behind_Master'};}$sqlQuery->finish;$dbh->disconnect();if ( $Slave_IO_Running eq "No" || $Slave_SQL_Running eq "No" ) {exit 1;} else {if ( $Seconds_Behind_Master > $SBM ) {exit 1;} else {exit 0;}}
注意:在运行mysql的检测文件【/etc/keepalived/check_slave.pl 127.0.0.1】时会报如下错误:
《1》“-bash: ./check_slave.pl: Permission denied”(即:该文件没有权限)【解决办法是:直接给该文件添加执行权限(chmod 755 /etc/keepalived/check_slave.pl)】。
《2》“Can't locate DBI.pm in @INC (you may need to install the DBI module) XXX”(即:缺少DBI依赖库)【解决办法是:直接安装perl的DBI依赖库(yum install perl-DBI -y)】。
《3》“Can't locate DBD/mysql.pm in @INC (you may need to install the DBD::mysql module)XXX”(即:缺少DBD依赖库)【解决办法是:直接安装perl的DBD依赖库(yum install perl-DBD-mysql -y)】。
3.2、在DB2配置keepalived从节点
#安装配置keepalived实现MySQL双主高可用流程#1-使用yum在线安装keepalived
yum install keepalived -y#2-进入keepalived的配置文件路径进行配置
cd /etc/keepalived/
cp -p keepalived.conf keepalived.conf.sample
vi keepalived.conf#2.1-【/etc/keepalived/keepalived.conf】文件的详细内容如下:! Configuration File for keepalivedglobal_defs {notification_email {ck@163.comck@qq.com }notification_email_from ckDB1smtp_server 192.168.1.100smtp_connect_timeout 30router_id MYSQL_DEVEL
}vrrp_script check_mysqld {script "/etc/keepalived/check_slave.pl 127.0.0.1"interval 2
}vrrp_instance VI_1 {state BACKUPinterface ens33virtual_router_id 51priority 80advert_int 1authentication {auth_type PASSauth_pass qwer1234}track_script {check_mysqld}virtual_ipaddress {192.168.1.227/24 dev ens33}
}#3-编辑mysql的检测脚本【/etc/keepalived/check_slave.pl】
vi check_slave.pl
chmod 755 check_slave.pl
#3.1-【check_slave.pl】脚本编辑完成后可以在Linux中进行测试(若结果返回0则表示mysql是正常运行中,否则就是异常的)
yum install perl-DBI perl-DBD-mysql -y
./check_slave.pl 127.0.0.1
echo $?
3.3、启动keepalived服务和设置开机自启
#先启动DB1(192.168.1.10)服务器上的keepalived服务,并查看对应的日志信息,接着设置keepalived服务开机自启、查看VIP(192.168.1.227)是否绑定在网卡ens33上;DB1启动没问题后就可以一样的操作DB2数据库的Keepalived服务了。
systemctl start keepalived
tail -f /var/log/messages
systemctl enable keepalived.service
ip addr
四、测试
4.1、测试MySQL的主从同步功能
为了验证MySQL的主从同步功能,我们可以到DB1(192.168.1.10)服务器上登录MySQL Server中创建一个数据库和表内容,然后再到DB2(192.168.1.40)的MySQL Server中查看是否有同步。
#测试MySQL的主从同步功能流程(可以相互在自己库中创建数据库表和内容到对方数据库查看是否同步)#1-登录DB1(192.168.1.10)的MySQL Server数据库创建名为ckdb的数据库和testck的表及其给表插入数据
/usr/local/mysql/mysql-8.0.43/bin/mysql -uroot -p
show databases;
create database ckdb;
show databases;
use ckdb;
show tables;
create table testck(id int not null primary key auto_increment, name nvarchar(12), sex int, age int);
show tables;
desc testck;
insert into testck(name,sex,age)values('张三',1,25),('李四',1,24),('周茜',0,23);#2-登录DB2(192.168.1.40)的MySQL Server数据库,然后查看是否存在ckdb数据库及其该库下的testck表和表中的数据是否有【张三、李四、周茜】这三个人(若都有则表示主从同步没有问题,否则就是有问题的)
4.2、测试keepalived的高可用
为了测试KeepAlived实现的故障转移功能,需要模拟一些故障(比如:可以通过断开DB1主机的网络、关闭DB1主机、关闭DB1上mysql服务等各种操作实现)。
#测试keepalived的高可用#1-在DB1所在的服务器上新开一个终端并监测message日志
tail -f /var/log/messages
#1.1-在DB1所在的服务器上再新开一个终端用来停止mysql服务(然后查看DB1监测的message日志信息)
systemctl stop mysqld.service
#1.2-此时使用VIP地址访问数据库(可用telnet来测试【telnet 192.168.1.227 13336】若可通则表示高可用是可以正常漂移IP到备用节点中,否则就是失败的)
telnet 192.168.1.227 13336
#1.3-查看DB1所在的VIP是否还绑定在网卡上(若:VIP没有绑定则表示成功)
ip addr#2-再次恢复DB1所在服务器上的mysql服务(然后查看DB1监测的message日志信息)
systemctl start mysqld.service
#2.1-查看DB1所在的VIP是否还绑定在网卡上(若:VIP有绑定则表示成功,否则keepalived是有问题的)
ip addr
4.3、测试停止DB1的slave的主从复制后的高可用
#测试停止DB1的slave后的主从复制高可用#1-先修改DB1主机的名称;然后在修改DB2主机的名称后,重启服务器
hostnamectl set-hostname db1
hostname
reboothostnamectl set-hostname db2
hostname
reboot#2-登录DB1、DB2的mysql server中创建一个用户ck可以让192.168.1.9设备登录且授予其管理员权限、查看当前所在主机的名称
/usr/local/mysql/mysql-8.0.43/bin/mysql -uroot -p
create user ck@'192.168.1.9' identified by 'qwer1234';
grant all on *.* to ck@'192.168.1.9';
flush privileges;
select @@hostname;#3-登录DB1的mysql并停止它的salve
/usr/local/mysql/mysql-8.0.43/bin/mysql -uroot -p
stop replica;
show replica status\G;#4-使用192.168.1.9服务器远程登录VIP并查看当前是哪个服务器(从结果可以看到是db2,这符合我们keepalived的故障ip漂移需求,满足高可用)
/usr/local/mysql/mysql-8.4.6/bin/mysql -uck -p -h 192.168.1.227 -P 13336
select @@hostname;#5-当我们恢复DB1的slave后,再次使用192.168.1.9服务器远程登录VIP并查看当前是哪个服务器(此时我们可以从结果看到是db1,这符合我们keepalived的故障ip漂移需求,满足高可用)
start replica;
show replica status\G;