[TOC]
一、环境准备
IP
主机名
角色
OS
192.168.96.136
mysql-master
mysql master、MHA manager、MHA node
Centos7
192.168.96.142
mysql-slave1
mysql slave1、MHA node
Centos7
192.168.96.143
mysql-slave2
mysql slave2、MHA node
Centos7
1、配置hosts 1 2 3 192.168.96.136 mysql-master 192.168.96.142 mysql-slave1 192.168.96.143 mysql-slave2
2、关闭防火墙 1 2 systemctl stop firewalld systemctl disable firewalld
3、禁用SELinux 1 2 3 4 5 6 swapoff -a free sed -ri 's/.*swap.*/#&/' /etc/fstab
4、关闭swap 1 2 3 4 5 6 swapoff -a free sed -ri 's/.*swap.*/#&/' /etc/fstab
5、配置互信(3台机器互相发送公钥) 1 2 3 4 ssh-keygen ssh-copy-id mysql-master ssh-copy-id mysql-slave1 ssh-copy-id mysql-slave2
二、mysql主从部署 1)安装mysql(MySQL5.7.29) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 mkdir -p /opt/mysql-mha; cd /opt/mysql-mha wget https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm rpm -ivh mysql80-community-release-el7-3.noarch.rpm rpm --import http://repo.mysql.com/RPM-GPG-KEY-mysql-2022 yum makecache yum repolist all | grep mysql yum -y install yum-utils yum-config-manager --disable mysql80-community yum-config-manager --enable mysql57-community yum module disable mysql yum install mysql-community-server mysql -y
2)mysql 节点配置 1、修改配置文件 修改mysql的所有节点mysql的主配置文件 (/etc/my.cnf)Master 节点
1 2 3 4 server-id = 1 log -bin=mysql-binbinlog_format=mixed log -slave-updates=true
Slave1,Slave2节点
1 2 3 4 server-id = 2 (slave3节点,则server-id=3。三台节点server-id不可重复) log_bin=mysql-bin relay-log=relay-log-bin relay-log-index=slave-relay-bin.index
3、启动服务
5、设置root密码 1 2 3 4 5 6 7 8 grep 'temporary password' /var/log /mysqld.log mysql -uroot -p set global validate_password_policy=0;set global validate_password_length=1;ALTER user 'root' @'localhost' IDENTIFIED BY '123456' ;
3)配置mysql 一主两从 1、 所有数据库节点进行mysql授权 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 mysql -uroot -p 123456 set global validate_password_policy=0;set global validate_password_length=1;grant replication slave on *.* to 'slave' @'192.168.96.%' identified by '123456' ; grant all on *.* to 'mha' @'192.168.96.%' identified by '123456' ; grant all on *.* to 'mha' @'%' identified by '123456' ; FLUSH PRIVILEGES;
2、在主库查看二进制文件和偏移量(master节点) 1 2 3 mysql show master status;
3、slave1,slave2 执行同步操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 change master to master_host='192.168.96.136' , master_user='slave' , master_password='123456' , master_log_file='mysql-bin.000001' , master_log_pos=154; start slave; show slave status \G ........... Slave_IO_Running: Yes Slave_SQL_Running: Yes .........
4、两个从库都设置为只读模式 1 2 3 4 5 6 mysql set global read_only=1;show global variables like 'read_only' ;
三、MHA概述
MHA(Master High Availability)是由日本人yoshinorim开发的一款成熟且开源的MySQL高可用程序,它实现了MySQL主从环境下MASTER宕机后能够自动进行单次故障转移的功能,其本身由perl语言编写,安装方便使用简单。
MHA官网:https://code.google.com/archive/p/mysql-master-ha/ GitHub地址:https://github.com/yoshinorim/mha4mysql-manager 文档:https://github.com/yoshinorim/mha4mysql-manager/wiki
四、MHA架构 当一个 master 崩溃时,MHA 会恢复下面的 rest slave。
五、MHA 组件 MHA 由 MHA Manager 和 MHA Node 组成,如下所示:
MHA Manager有监控MySQL master、控制master故障转移等管理程序。
MHA 节点具有故障转移辅助脚本,例如解析 MySQL 二进制/中继日志,识别中继日志位置,中继日志应从哪个位置应用到其他从站,将事件应用到目标从站等。MHA 节点在每个 MySQL 服务器上运行。
当 MHA Manager 进行故障转移时,MHA Manager 通过 SSH 连接 MHA Node 并在需要时执行 MHA Node 命令。
六、安装MHA软件 下载地址:https://github.com/yoshinorim/mha4mysql-manager/wiki/Downloads
1)所有节点安装MHA node软件 下载地址:https://github.com/yoshinorim/mha4mysql-node/releases/tag/v0.58
1 2 3 4 5 6 7 8 9 10 cd /opt/mysql-mhayum install perl-DBD-MySQL -y wget https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-node-0.58-0.el7.centos.noarch.rpm rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm
2) 安装mha manager(master节点上) 1、安装mha manager 1 2 3 4 5 6 7 8 9 yum -y install epel-release yum -y install perl-Config-Tiny perl-Time-HiRes perl-Parallel-ForkManager perl-Log-Dispatch perl-DBD-MySQL ncftp wget https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.58/mha4mysql-manager-0.58-0.el7.centos.noarch.rpm rpm -ivh mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
2、 编写master_ip_failover脚本(manager节点) /opt/mysql-mha/master_ip_failover,下面配置文件中会用到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 use strict; use warnings FATAL => 'all' ; use Getopt::Long; my ( $command , $orig_master_host , $orig_master_ip ,$ssh_user , $orig_master_port , $new_master_host , $new_master_ip ,$new_master_port , $orig_master_ssh_port ,$new_master_ssh_port ,$new_master_user ,$new_master_password ); my $vip = '192.168.96.200/24' ; my $key = '1' ; my $ssh_start_vip = "sudo /sbin/ifconfig ens33:$key $vip " ; my $ssh_stop_vip = "sudo /sbin/ifconfig ens33:$key down" ; my $ssh_Bcast_arp = "sudo /sbin/arping -I bond0 -c 3 -A $vip " ; 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 , 'orig_master_ssh_port=i' => \$orig_master_ssh_port , 'new_master_host=s' => \$new_master_host , 'new_master_ip=s' => \$new_master_ip , 'new_master_port=i' => \$new_master_port , 'new_master_ssh_port' => \$new_master_ssh_port , 'new_master_user' => \$new_master_user , 'new_master_password' => \$new_master_password ); exit &main(); sub main { $ssh_user = defined $ssh_user ? $ssh_user : 'root' ; print "\n\nIN SCRIPT TEST====$ssh_user |$ssh_stop_vip ==$ssh_user |$ssh_start_vip ===\n\n" ; if ( $command eq "stop" || $command eq "stopssh" ) { 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" ) { my $exit_code = 10; eval { print "Enabling the VIP - $vip on the new master - $new_master_host \n" ; &start_vip(); &start_arp(); $exit_code = 0; }; if ($@ ) { warn $@ ; exit $exit_code ; } exit $exit_code ; } elsif ( $command eq "status" ) { print "Checking the Status of the script.. OK \n" ; exit 0; } else { &usage(); exit 1; } } sub start_vip () { `ssh $ssh_user \@$new_master_host \" $ssh_start_vip \"`; } sub stop_vip () { `ssh $ssh_user \@$orig_master_host \" $ssh_stop_vip \"`; } sub start_arp () { `ssh $ssh_user \@$new_master_host \" $ssh_Bcast_arp \"`; } sub usage { print "Usage: master_ip_failover --command=start|stop|stopssh|status --ssh_user=user --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" ; }
给该脚本添加可执行权限:
1 chmod a+x /opt/mysql-mha/master_ip_failover
3、 配置(manager节点) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 mkdir -p /opt/mysql-mha/mha-node mkdir -p /opt/mysql-mha/mha vim /opt/mysql-mha/mysql_mha.cnf ------------------------------------------------------------------------ [server default] user=mha password=123456 port=3306 manager_workdir=/opt/mysql-mha/mha manager_log=/opt/mysql-mha/manager.log master_binlog_dir=/var/lib/mysql remote_workdir=/opt/mysql-mha/mha-node repl_user=slave repl_password=123456 ping_interval=1 master_ip_failover_script=/opt/mysql-mha/master_ip_failover secondary_check_script=/usr/bin/masterha_secondary_check -s 192.168.96.142 -s 192.168.96.143 [server1] hostname=192.168.96.136 port=3306 ssh_user=root candidate_master=1 check_repl_delay=0 [server2] hostname=192.168.96.142 port=3306 ssh_user=root candidate_master=1 check_repl_delay=0 [server3] hostname=192.168.96.143 port=3306 ssh_user=root candidate_master=1 check_repl_delay=0
candidate_master=1
设置为候选master,设置该参数以后,发生主从切换以后将会将此从库提升为主库,即使这个从库不是集群中最新的slave,no_master=1正好相反
check_repl_delay=0
默认情况下如果一个slave落后master 超过100M的relay logs的话,MHA将不会选择该slave作为一个新的master, 因为对于这个slave的恢复需要花费很长时间;通过设置check_repl_delay=0,MHA触发切换在选择一个新的master的时候将会忽略复制延时,这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主在切换的过程中一定是新的master
5)在master上手动启动虚拟iP 第一次配置需要在master节点上手动启动虚拟IP,标签要和master_ip_faioverl配置文件中my $key = ‘1’; 一样
1 /sbin/ifconfig ens33:1 192.168.96.200/24
6)在manager 节点测试ssh 无密认证 1 masterha_check_ssh -conf=/opt/mysql-mha/mysql_mha.cnf
7)在manager 节点上测试mysql主从情况 1 masterha_check_repl -conf=/opt/mysql-mha/mysql_mha.cnf
8)在manage上启动mha 1 2 3 4 nohup masterha_manager \ --conf=/opt/mysql-mha/mysql_mha.cnf \ --remove_dead_master_conf \ --ignore_last_failover < /dev/null > /var/log /mha_manager.log 2>&1 &
--remove_dead_master_conf:该参数代表当发生主从切换后,老的主库的 ip 将会从配置文件中移除。
--manger_log:日志存放位置。
--ignore_last_failover:在缺省情况下,如果 MHA 检测到连续发生宕机,且两次宕机间隔不足 8 小时的话,则不会进行 Failover, 之所以这样限制是为了避免 ping-pong 效应。该参数代表忽略上次 MHA 触发切换产生的文件,默认情况下,MHA 发生切换后会在日志记目录,也就是上面设置的日志app1.failover.complete文件,下次再次切换的时候如果发现该目录下存在该文件将不允许触发切换,除非在第一次切换后收到删除该文件,为了方便,这里设置为–ignore_last_failover。
9)查看MHA状态 1 masterha_check_status --conf=/opt/mysql-mha/mysql_mha.cnf
10)查看MHA日志文件 1 cat /opt/mysql-mha/manager.log | grep "current master"
11)manager节点关闭manager服务 1 masterha_stop --conf=/opt/mysql-mha/mysql_mha.cnf
七、故障模拟与恢复 1)停掉mysql master
2)查看主备节点
1 2 3 4 mysql -uroot -p 123456
3)故障恢复 先在当前的主库服务器slave1上查看二进制日志和同步点
1 2 3 4 mysql -uroot -p 123456 show master status;
再在原master 服务器上执行同步操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 systemctl start mysqld mysql -uroot -p 123456 change master to master_host='192.168.96.143' , master_user='slave' , master_password='123456' , master_log_file='mysql-bin.000001' , master_log_pos=154; start slave; show slave status\G
常见报错解决:
说明机器之间的免密通信没有做好,可以把之前的密钥文件(/root/.ssh下的所有文件)全部删除,重新生成密钥并给每台机器发送自己的公钥。(3台机器之间一定要互相给公钥,自己给自己也要给!!)
一般是因为防火墙未关的原因或者是因为有的节点并没有设置对应要求的MySQL用户,导致无法连接。
如果在最后测试时,主库挂了之后,从库成功成为了主库,且主库与从库之间的数据也会同步,但是VIP并没有漂移过来,在配置文件确定没错的情况下,大概率是因为发生了脑裂,可以重新启动一下主节点和从节点机器试一下。
关于MHA-manager和主库是否要在一台机器的问题 根据MHA的设计,通常将MHA的管理节点和数据库节点分离,即管理节点不应该直接兼顾MySQL的主库角色。这是为了确保高可用解决方案的稳定性和可靠性,避免单点故障和资源争用。
但是公司中会由于服务器规模不够,会将其会组合在一块,这种场景就没有办法了。