二十二、Mysql之MHA
MHA(Master High Availability)是用Perl编写的一套非常流行和实用的MySQL高可用解决方案软件,它的作用是保证MySQL主从复制集群中主库的高可用性,同时保证整个集群业务服务不受影响。当主库异常宕机后,MHA能够在1~30秒的时间内实现故障自动检测和故障自动转移,选择一个最优的从库变成新的主库,同时使得其他的从库和新的主库继续保持数据一致的状态,同时还需要保证在数据库发生故障时,将集群所有数据的损失都降到最低。 在主从复制集群框架中,MHA方案能够很好地解决主从复制宕机切换过程中业务持续服务和数据一致性的问题。
整个MHA软件由两部分角色组成,即MHA Manager(管理节点)和MHA Node(数据节点)。MHA Manager服务可以独立部署在一台服务器(含虚拟机)上管理多个主从复制集群,也可以部署在某一台主从复制从节点或者其他应用服务器节点上,而MHA Node服务需要运行在每一个MySQL服务器上。MHA Manager会定时通过主库上的MHA Node服务监测主库,当主库出现故障时,它可以自动将最优从库(可以提前指定或由MHA判定)提升为新的主库,然后让所有其他的从库与新的主库重新保持正常的复制状态。故障的整个切换和转移的过程对客户以及应用程序几乎是完全透明的。
在MHA自动故障切换过程中,MHA试图从宕机的主服务器上保存二进制日志,最大程度的保证数据的不丢失,但这并不总是可行的。例如,如果主服务器硬件故障或无法通过ssh访问,MHA没法保存二进制日志,只进行故障转移而丢失了最新的数据。使用MySQL 5.6以上的半同步复制,可以大大降低数据丢失的风险。MHA可以与半同步复制结合起来。如果只有一个slave已经收到了最新的二进制日志,MHA可以将最新的二进制日志应用于其他所有的slave服务器上,因此可以保证所有节点的数据一致性。
目前MHA主要支持一主多从的架构,要搭建MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当master,一台充当备用master,另外一台充当从库,因为至少需要三台服务器,出于机器成本的考虑,淘宝也在该基础上进行了改造,目前淘宝TMHA已经支持一主一从。(出自:《深入浅出MySQL(第二版)》)。
Manaer节点负责监控所有Node节点(主和从的所有节点) 监控节点 (通过配置文件获取所有节点信息) 系统,网络,SSH连接性 主从状态,重点是主库 主库宕机处理过程 1. 选主 (1) 如果判断从库(position或者GTID),数据有差异,最接近于Master的slave,成为备选主;设置半同步从库,直接选择半同步的从库作为新的主库。 (2) 如果判断从库(position或者GTID),数据一致,按照配置文件顺序,选主. (3) 如果设定有权重(candidate_master=1),按照权重强制指定备选主. 1. 默认情况下如果一个slave落后master 100M的relay logs的话,即使有权重,也会失效. 2. 如果check_repl_delay=0的化,即使落后很多日志,也强制选择其为备选主 3. 数据补偿 (1) 当SSH能连接,从库对比主库GTID 或者position号,立即将二进制日志保存至各个从节点并且应用(save_binary_logs );从库通过MHA自带脚本程序,立即保存缺失部分的binlog (2) 当SSH不能连接, 对比从库之间的relaylog的差异(apply_diff_relay_logs);计算从库之间的relay-log的差异,补尝到其它从库。 4. Failover (1)将备选主进行身份切换,对外提供服务 (2)其余从库和新主库确认新的主从关系 5. 应用透明(VIP) 如果VIP机制,将VIP从原主库漂移到新主,让应用程序无感知 6. 故障切换通知(send_reprt) 发送告警邮件信息(可配置) 7. 二次数据补偿(binlog_server) 如果有binlog server机制会继续将binlog server中缺失部分的事务,补偿到新的主库。
Mysql主从复制-正常状态
Mysql主从复制-主库宕机
Mysql主从复制-原主恢复后
MHA Manager管理多组主从复制
三、MHA的软件包说明
1、Manager工具包主要包括以下几个工具:
masterha_check_ssh #检査MHA的SSH配置状态
masterha_check_repl #检査主从复制情况
masterha_manger #启动MHA
masterha_check_status #检测MHA的运行状态
masterha_mast er_monitor #检测master是否宕机
masterha_mast er_switch #控制故障转移(自动或手动)
masterha_conf_host #手动添加或删除server信息
masterha_secondary_check #建立TCP连接从远程服务器
masterha_stop #停止MHA
save_binary_1ogs #保存宕机的master的binlog
apply_diff_relay_logs #识别relay log的差异并应用于其它从节点
filter_mysqlbinlog #防止回滚事件一MHA已不再使用这个工具
purge_relay_logs #清除中继日志一不会阻塞SQL线程
1、实验环境
System OS: CentOS Linux release 7.6.1810 (Core) mysql5.7 version: mysql-5.7.20-linux-glibc2.12-x86_64.tar.gz db01 10.0.0.101 mysql5.7 master+mha mha-node db02 10.0.0.102 mysql5.7 slave1+mha mha-node db03 10.0.0.103 mysql5.7 slave2+mha mha-node node4 10.0.0.104 mha manage mysql5.7 binlog-server mha-node 所有机器统一环境,关闭防火墙和Selinux 三台MySQL机器,安装mysql 5.7,安装目录/app/mysql;数据目录 /data/mysql/data;binlog目录/data/mysql/binlog;均为二进制安装。 msyql主从为GTID主从。
详细部署步骤:https://www.cnblogs.com/yaokaka/p/13914362.html
4、配置GTID主从
4.1主库my.cnf配置
#master:db01 cat >>/etc/my.cnf<<EOF [mysqld] basedir=/app/mysql/ datadir=/data/mysql/data socket=/tmp/mysql.sock server_id=101 port=3306 secure-file-priv=/tmp autocommit=0 log_bin=/data/mysql/binlog/mysql-bin binlog_format=row gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1 [mysql] prompt=db01 [\d]> EOF
#slave1:db02 cat >>/etc/my.cnf<<EOF [mysqld] basedir=/app/mysql/ datadir=/data/mysql/data socket=/tmp/mysql.sock server_id=102 port=3306 secure-file-priv=/tmp autocommit=0 log_bin=/data/mysql/binlog/mysql-bin binlog_format=row gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1 [mysql] prompt=db02 [\d]> EOF #slave2:db03 cat >>/etc/my.cnf<<EOF [mysqld] basedir=/app/mysql/ datadir=/data/mysql/data socket=/tmp/mysql.sock server_id=103 port=3306 secure-file-priv=/tmp autocommit=0 log_bin=/data/mysql/binlog/mysql-bin binlog_format=row gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1 [mysql] prompt=db03 [\d]> EOF
#mater db01 [root@db01 ~]# mysql -uroot db01 [(none)]>grant replication slave on *.* to repl@'10.0.0.%' identified by '123';
#slave1 db02和slave2 db03 #1.配置参数如下 mysql> change master to master_host= '10.0.0.101', master_user= 'repl', master_password= '123', master_auto_position= 1; #启动slave mysql> start slave; #查看slave同步状态 mysql> show slave status\G ...... Slave_IO_Running: Yes Slave_SQL_Running: Yes ......
#1.所有库修改my.cnf配置文件,添加以下参数 [mysqld] relay_log_purge = 0 #2.重启mysql /etc/init.d/mysqld restart #3、在数据库下运行该命令可以不用重启数据库 mysql> set global relay_log_purge = 0; #3.查看是否关闭relaylog mysql> show variables like '%relay%'; 提示:如果不想重启数据库可在mysql命令行全局设置 mysql> set global relay_log_purge = 0;
5、安装MHA软件
本次MHA的部署基于GTID复制成功构建,普通主从复制也可以构建MHA架构。
下载mha软件,mha官网:https://code.google.com/archive/p/mysql-master-ha/
github下载地址:https://github.com/yoshinorim/mha4mysql-manager/wiki/Downloads
mha4mysql-manager-0.56-0.el6.noarch.rpm mha4mysql-node-0.56-0.el6.noarch.rpm
#1.安装依赖包 yum install perl-DBD-MySQL -y #2.上传mha安装包mha4mysql-node-0.56-0.el6.noarch.rpm mkdir /app cd /app 上传mha4mysql-node-0.56-0.el6.noarch.rpm #3.在所有主从节点安装node rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm
#1、master db01 db01 [(none)]> grant all privileges on *.* to mha@'10.0.0.%' identified by 'mha'; #2.验证账号是否同步成功 slave1 db02 db02 [(none)]>select user,host from mysql.user; +---------------+-----------+ | user | host | +---------------+-----------+ | mha | 10.0.0.% | | repl | 10.0.0.% | | mysql.session | localhost | | mysql.sys | localhost | | root | localhost | +---------------+-----------+ 5 rows in set (0.00 sec)
#如果不创建命令软连接,检测mha复制情况的时候会报错 ln -s /app/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog ln -s /app/mysql/bin/mysql /usr/bin/mysql #MHA源码包中设置的mysqlbinlog和mysql的默认路径为/usr/bin
这里以单独的机器node4部署mha管理节点
6.1.安装mha管理软件和相关依赖包
#node4 #1.安装epel源 wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo #2.安装mha manager依赖包 yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes perl-DBD-MySQL #4、上传mha4mysql-manager-0.56-0.el6.noarch和mha4mysql-node-0.56-0.el6.noarch.rpm mkdir /app 上传mha4mysql-manager-0.56-0.el6.noarch #5.安装manager管理软件 cd /app rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm [root@node4 app]# rpm -qa |grep mha mha4mysql-node-0.56-0.el6.noarch mha4mysql-manager-0.56-0.el6.noarch
#node4 mkdir -p /etc/mha #创建必须目录 mkdir -p /var/log/mha/app1 #创建日志,目录可以管理多套主从复制
cat >>/etc/mha/app1.cnf<<EOF [server default] manager_log=/var/log/mha/app1/manager manager_workdir=/var/log/mha/app1 master_binlog_dir=/data/mysql/binlog user=mha password=mha ping_interval=2 repl_password=123 repl_user=repl ssh_user=root [server1] hostname=10.0.0.101 port=3306 [server2] hostname=10.0.0.102 port=3306 [server3] hostname=10.0.0.103 port=3306 EOF
[server default] #设置manager的工作目录 manager_workdir=/var/log/mha/app1 #设置manager的日志 manager_log=/var/log/masterha/app1/manager.log #设置master 保存binlog的位置,以便MHA可以找到master的日志,我这里的也就是mysql的数据目录 master_binlog_dir=/app/mysql/binlog #设置自动failover时候的切换脚本 master_ip_failover_script= /usr/local/bin/master_ip_failover #设置手动切换时候的切换脚本 master_ip_online_change_script= /usr/local/bin/master_ip_online_change #设置mysql中root用户的密码,这个密码是前文中创建监控用户的那个密码 password=mha #设置监控用户mha user=mha #设置监控主库,发送ping包的时间间隔,尝试四次没有回应的时候自动进行failover ping_interval=1 #设置远端mysql在发生切换时binlog的保存位置 remote_workdir=/tmp #设置主从复制用户的密码 repl_password=123 #设置主从复制环境中用户名 repl_user=repl #设置发生切换后发送的报警的脚本 report_script=/usr/local/send_report #MHA Manager节点到MASTER节点(db01)的监控之间出现问题时,MHA Manager将会尝试从其他路径登录到MASTER(db01)节点。 secondary_check_script= /usr/local/bin/masterha_secondary_check -s db03(server3) -s db02(server2) --user=root --master_host=db01(server1) --master_ip=10.0.0.101 --master_port=3306 #设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机放在发生脑裂,这里没有使用) shutdown_script="" #设置ssh的登录用户名 ssh_user=root [server1] hostname=10.0.0.101 port=3306 [server2] hostname=10.0.0.102 port=3306 [server3] hostname=10.0.0.103 port=3306 #设置为候选master,如果设置该参数以后,发生主从切换以后将会将此从库提升为主库,即使这个主库不是集群中事件最新的slave candidate_master=1 #默认情况下如果一个slave落后master 100M的relay logs的话,MHA将不会选择该slave作为一个新的master, 因为对于这个slave的恢复需要花费很长时间,通过设置check_repl_delay=0,MHA触发切换 在选择一个新的master的时候将会忽略复制延时,这个参数对于设置了candidate_master=1 的主机非常有用,因为这个候选主在切换的过程中一定是新的master check_repl_delay=0
#db01 rm -rf /root/.ssh ssh-keygen cd /root/.ssh mv id_rsa.pub authorized_keys scp -r /root/.ssh 10.0.0.0.102:/root scp -r /root/.ssh 10.0.0.0.103:/root scp -r /root/.ssh 10.0.0.0.104:/root 各节点验证 db01: ssh 10.0.0.101 date ssh 10.0.0.102 date ssh 10.0.0.103 date ssh 10.0.0.104 date db02: ssh 10.0.0.101 date ssh 10.0.0.102 date ssh 10.0.0.103 date ssh 10.0.0.104 date db03: ssh 10.0.0.101 date ssh 10.0.0.102 date ssh 10.0.0.103 date ssh 10.0.0.104 date node4: ssh 10.0.0.101 date ssh 10.0.0.102 date ssh 10.0.0.103 date ssh 10.0.0.104 date
8.1测试ssh
[root@node4 app]# masterha_check_ssh --conf=/etc/mha/app1.cnf Sat Dec 5 21:47:50 2020 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping. Sat Dec 5 21:47:50 2020 - [info] Reading application default configuration from /etc/mha/app1.cnf.. Sat Dec 5 21:47:50 2020 - [info] Reading server configuration from /etc/mha/app1.cnf.. Sat Dec 5 21:47:50 2020 - [info] Starting SSH connection tests.. Sat Dec 5 21:47:51 2020 - [debug] Sat Dec 5 21:47:50 2020 - [debug] Connecting via SSH from root@10.0.0.101(10.0.0.101:22) to root@10.0.0.102(10.0.0.102:22).. Sat Dec 5 21:47:50 2020 - [debug] ok. Sat Dec 5 21:47:50 2020 - [debug] Connecting via SSH from root@10.0.0.101(10.0.0.101:22) to root@10.0.0.103(10.0.0.103:22).. Sat Dec 5 21:47:51 2020 - [debug] ok. Sat Dec 5 21:47:52 2020 - [debug] Sat Dec 5 21:47:51 2020 - [debug] Connecting via SSH from root@10.0.0.102(10.0.0.102:22) to root@10.0.0.101(10.0.0.101:22).. Sat Dec 5 21:47:51 2020 - [debug] ok. Sat Dec 5 21:47:51 2020 - [debug] Connecting via SSH from root@10.0.0.102(10.0.0.102:22) to root@10.0.0.103(10.0.0.103:22).. Sat Dec 5 21:47:51 2020 - [debug] ok. Sat Dec 5 21:47:53 2020 - [debug] Sat Dec 5 21:47:51 2020 - [debug] Connecting via SSH from root@10.0.0.103(10.0.0.103:22) to root@10.0.0.101(10.0.0.101:22).. Sat Dec 5 21:47:51 2020 - [debug] ok. Sat Dec 5 21:47:51 2020 - [debug] Connecting via SSH from root@10.0.0.103(10.0.0.103:22) to root@10.0.0.102(10.0.0.102:22).. Sat Dec 5 21:47:52 2020 - [debug] ok. Sat Dec 5 21:47:53 2020 - [info] All SSH connection tests passed successfully.
[root@node4 app]# masterha_check_repl --conf=/etc/mha/app1.cnf
最后提示MySQL Replication Health is OK.则主从正常
经过上面的部署过后,MHA架构已经搭建完成
[root@node4 app]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &
[root@node4 app]# masterha_check_status --conf=/etc/mha/app1.cnf app1 (pid:8517) is running(0:PING_OK), master:10.0.0.101
MHA部署成功
五、MHA故障切换
当原主库db01宕机后,因为从库db02和db03的数据一致,因为按照配置文件顺序由db02接管成为主,db03会自动将与原主库db01的主从关系断掉,并与新主库db02建立主从关系。这时候当原主db01恢复正常后,需要通过change master to跟db02主进行主从复制同步,成为db02的从库。
每当MHA完成一次故障的切换,就会自动停止MHA Manager进程。
5.1.手动停止主库(目前的主库是db01)
[root@db01 ~]# systemctl stop mysqld [root@db01 ~]# ps -ef |grep mysqld root 8389 8350 0 15:22 pts/2 00:00:00 grep --color=auto mysqld [root@db01 ~]# pidof mysqld [root@db01 ~]#
#node4 mha-manager [root@node4 ~]# tail /var/log/mha/app1/manager Master 10.0.0.101(10.0.0.101:3306) is down! Check MHA Manager logs at node4:/var/log/mha/app1/manager for details. Started automated(non-interactive) failover. Selected 10.0.0.102(10.0.0.102:3306) as a new master. 10.0.0.102(10.0.0.102:3306): OK: Applying all logs succeeded. 10.0.0.103(10.0.0.103:3306): OK: Slave started, replicating from 10.0.0.102(10.0.0.102:3306) 10.0.0.102(10.0.0.102:3306): Resetting slave info succeeded. Master failover to 10.0.0.102(10.0.0.102:3306) completed successfully. #可以从日志上看到主库db01已经down了,从库db02成为了新的主库
#db02 db02 [(none)]>show slave status\G Empty set (0.00 sec) #db03 db03 [(none)]>show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.0.0.102 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000003 Read_Master_Log_Pos: 1566 Relay_Log_File: db03-relay-bin.000002 Relay_Log_Pos: 414 Relay_Master_Log_File: mysql-bin.000003 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 1566 Relay_Log_Space: 620 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 102 Master_UUID: 7ffb2b2e-369e-11eb-add3-000c29913f16 Master_Info_File: /data/mysql/data/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: 6aeade62-3621-11eb-b83c-000c294bdbec:1-4 Auto_Position: 1 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.01 sec) #db02已经成为新的主库,且db03已经与新主库db02建立的主从关系
原主库db01宕机后,mha-manager (node4)在完成一次切换后也自动停止了。
[root@node4 ~]# ps -ef|grep mha root 9230 8888 0 15:28 pts/1 00:00:00 grep --color=auto mha
[root@node4 ~]# cat /etc/mha/app1.cnf [server default] manager_log=/var/log/mha/app1/manager manager_workdir=/var/log/mha/app1 master_binlog_dir=/data/mysql/binlog password=mha ping_interval=2 repl_password=123 repl_user=repl ssh_user=root user=mha [server2] hostname=10.0.0.102 port=3306 [server3] hostname=10.0.0.103 port=3306
原主库恢复后,只能为当时主库的从库。
6.1恢复故障的数据库db01
1、数据库故障不严重,不需要重做部署数据库或初始化数据库,可以直接重新建议新的主从关系。 2、数据库物理损坏严重,恢复数据库时,需要使用新数据库的全备来做恢复,然后再建立新的主从关系。
原主库db01恢复好后,只能成为新主库db02的从库.
将MHA的日志文件的change master to 过滤出来,修改下password
密码,然后使用该参数到原主库里恢复主从.
#mha-manager(node4)上操作 [root@node4 ~]# grep -i "change master to " /var/log/mha/app1/manager Sun Dec 6 15:22:28 2020 - [info] All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='10.0.0.102', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='xxx'; #把MASTER_PASSWORD='xxx'更改为设置的密码; #也可以在从库db03上show slave status\G来查看相应的信息 CHANGE MASTER TO MASTER_HOST='10.0.0.102', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';
#db01 db01 [(none)]>CHANGE MASTER TO MASTER_HOST='10.0.0.102', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123'; db01 [(none)]>start slave; Query OK, 0 rows affected (0.00 sec) db01 [(none)]>show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.0.0.102 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000003 Read_Master_Log_Pos: 1566 Relay_Log_File: db01-relay-bin.000002 Relay_Log_Pos: 414 Relay_Master_Log_File: mysql-bin.000003 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: ...... #db01与新主库db02的主从建立完成
恢复[server1]db01的配置
[root@node4 ~]# vim /etc/mha/app1.cnf [server default] manager_log=/var/log/mha/app1/manager manager_workdir=/var/log/mha/app1 master_binlog_dir=/data/mysql/binlog password=mha ping_interval=2 repl_password=123 repl_user=repl ssh_user=root user=mha [server1] hostname=10.0.0.101 port=3306 [server2] hostname=10.0.0.102 port=3306 [server3] hostname=10.0.0.103 port=3306
[root@node4 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 & [1] 9297 [root@node4 ~]# ps -ef|grep mha root 9297 8888 1 15:56 pts/1 00:00:00 perl /usr/bin/masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover root 9318 8888 0 15:57 pts/1 00:00:00 grep --color=auto mha [root@node4 ~]# masterha_check_status --conf=/etc/mha/app1.cnf app1 (pid:9297) is running(0:PING_OK), master:10.0.0.102
通过MHA自带的脚本实现master_ip_failover(vip、漂移、应用透明)
IP漂移的两种方式:
1、通过keepalived的方式,管理虚拟IP的漂移,需要配置漂移数据库的权重,避免keepalive漂移跟MHA漂移不一致问题。(不推荐使用) 2、通过MHA自带脚本方式,管理虚拟IP的漂移(强烈推荐)
#!/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 = '10.0.0.55/24'; my $key = '0'; my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip"; my $ssh_stop_vip = "/sbin/ifconfig eth0:$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" ) { 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(); $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() { return 0 unless ($ssh_user); `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"; } #脚本部分修改内容如下: #my $vip = '10.0.0.55/24'; #VIP地址(该地址要选择在现网中未被使用的) #my $key = '1'; #my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip"; #启动VIP时的网卡名 #my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down"; #关闭VIP时的网卡名
7.2将MHA脚本上传到/usr/bin目录并添加执行权限
1、上传MHA脚本 2、[root@node4 bin]# chmod +x /usr/bin/master_ip_failover
叫VIP设置为10.0.0.55/24
在mha配置文件的[server default]模块下添加 [server default] master_ip_failover_script=/usr/local/bin/master_ip_failover manager_log=/var/log/mha/app1/manager manager_workdir=/var/log/mha/app1 master_binlog_dir=/data/mysql/binlog password=mha ping_interval=2 repl_password=123 repl_user=repl ssh_user=root user=mha [server1] hostname=10.0.0.101 port=3306 [server2] hostname=10.0.0.102 port=3306 [server3] hostname=10.0.0.103 port=3306
#db02 手工在主库上绑定vip,注意一定要和配置文件中的ethN一致,我的是eth0:0(1是key指定的值) [root@db02 ~]# ifconfig eth0:0 10.0.0.55/24 [root@db02 ~]# ifconfig eth0:0 eth0:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.0.0.55 netmask 255.255.255.0 broadcast 10.0.0.255 ether 00:0c:29:91:3f:16 txqueuelen 1000 (Ethernet)
#mha-manager(node4) [root@node4 ~]# masterha_stop --conf=/etc/mha/app1.cnf Stopped app1 successfully. [root@node4 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 & [1] 11941
现有主库db02宕机后,因为db01和db03的数据一样,会按照配置文件选择db01会新的主库,db03会与db01建立新的主从。vip会漂移到db01上。
#1、db02宕机处理 [root@db02 ~]# ifconfig eth0:0 eth0:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.0.0.55 netmask 255.255.255.0 broadcast 10.0.0.255 ether 00:0c:29:91:3f:16 txqueuelen 1000 (Ethernet) [root@db02 ~]# systemctl stop mysqld [root@db02 ~]# ifconfig eth0:0 eth0:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 ether 00:0c:29:91:3f:16 txqueuelen 1000 (Ethernet) #VIP已经消失 #2、在db01上查看vip [root@db01 ~]# ifconfig eth0:0 eth0:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.0.0.55 netmask 255.255.255.0 broadcast 10.0.0.255 ether 00:0c:29:4b:db:ec txqueuelen 1000 (Ethernet) #VIP已经漂移到db01上 #3、查看db01和db03的slave状态 #db01 db01 [(none)]>show slave status\G Empty set (0.00 sec) #db03 db03 [(none)]>show slave status \G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.0.0.101 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000004 Read_Master_Log_Pos: 194 Relay_Log_File: db03-relay-bin.000002 Relay_Log_Pos: 367 Relay_Master_Log_File: mysql-bin.000004 Slave_IO_Running: Yes Slave_SQL_Running: Yes ...... #db01已成为新的主库,db03与db01重新建立了主从
1、恢复db02数据库 1)数据库故障不严重,不需要重做部署数据库或初始化数据库,可以直接重新建议新的主从关系。 2)数据库物理损坏严重,恢复数据库时,需要使用新数据库的全备来做恢复,然后再建立新的主从关系。 2、将原主库db2,通过change master to指向新的master #mha-manager(node4)上操作 [root@node4 ~]# grep -i "change master to " /var/log/mha/app1/manager Sun Dec 6 17:15:20 2020 - [info] All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='10.0.0.101', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='xxx'; #把MASTER_PASSWORD='xxx'更改为设置的密码; #也可以在从库db03上show slave status\G来查看相应的信息 CHANGE MASTER TO MASTER_HOST='10.0.0.101', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123'; #db02将原主库db2,通过change master to指向新的master,并启动主从 db02 [(none)]>CHANGE MASTER TO MASTER_HOST='10.0.0.101', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123'; db02 [(none)]>start slave; db02 [(none)]>show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.0.0.101 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000004 Read_Master_Log_Pos: 194 Relay_Log_File: db02-relay-bin.000002 Relay_Log_Pos: 367 Relay_Master_Log_File: mysql-bin.000004 Slave_IO_Running: Yes Slave_SQL_Running: Yes 。。。。。。 3、把db02[server2]添加会mha的配置文件并启动mha [root@node4 bin]# vim /etc/mha/app1.cnf [server default] manager_log=/var/log/mha/app1/manager manager_workdir=/var/log/mha/app1 master_binlog_dir=/data/mysql/binlog master_ip_failover_script=/usr/local/bin/master_ip_failover password=mha ping_interval=2 repl_password=123 repl_user=repl ssh_user=root user=mha [server1] hostname=10.0.0.101 port=3306 [server2] hostname=10.0.0.102 port=3306 [server3] hostname=10.0.0.103 port=3306 4、启动mha [root@node4 bin]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 & [1] 12518 [root@node4 bin]# masterha_check_status --conf=/etc/mha/app1.cnf app1 (pid:12518) is running(0:PING_OK), master:10.0.0.101
主库宕机,也许会造成主库binlog
复制不及时而导致数据丢失的情况出现,因此配置binlog-server
进行实时同步备份,是必要的一种安全手段。
这里就用db04来演示保存来自主库binlog的服务器,必须要有mysql5.6以上的版本。本实验为mysql为5.7.20。
binlog-server部署在mha-manager(node4)上,最好独立一台服务器
8.1MHA配置binlog-server
#在mha上的app1.cnf配置文件最后添加如下参数 [root@mha /]# cat /etc/mha/app1.cnf [binlog1] no_master=1 hostname=10.0.0.104 master_binlog_dir=/data/mysql/binlog_server/ 参数解释: [binlog1] #添加binlog模块 no_master= (0|1) #1表示永远不提升为master,该节点不参与主从的选举 hostname=10.0.0.104 #指定binlog-server地址10.0.0.104 master_binlog_dir=/binlog_server/ #binglog-server保存binlog保存目录(不能和主库保存位置重复)
#1、创建binlog_server目录并授权 [root@node4 ~]# mkdir /binlog_server [root@node4 ~]# chown -R mysql.mysql /binlog_server #2、进入binlog_server备份目录,必须在目录下拉取binlog日志 [root@node4 ~]# cd /binlog_server/ #3、查看从库同步最少的binglog信息 #db02 db02 [(none)]>show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.0.0.101 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000004 Read_Master_Log_Pos: 194 ....... 从mysql-bin.000004开始拉取 #4、拉取主库的binlog日志,拉取日志的起点,需要按照目前从库的已经获取到的二进制日志点为起点 [root@node4 binlog_server]#mysqlbinlog -R --host=10.0.0.101 --user=mha --password=mha --raw --stop-never mysql-bin.000004 & [root@node4 binlog_server]# ll total 4 -rw-r----- 1 root root 194 Dec 6 21:06 mysql-bin.000004 #日志已经拉取过来了 参数解释: -R --host=10.0.0.101 #指定主库的地址,向主库拉取binlog --user=mha #指定之前在主库所创建的MHA的管理用户 --password=mha #指定之前在主库所创建MHA管理用户对应的密码 --stop-never #要查看主库的binglog文件最开始的位置
#1.停止mha [root@node4 binlog_server]# masterha_stop --conf=/etc/mha/app1.cnf #2.启动mha [root@node4 binlog_server]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &
#1、在主库上刷新binlog日志 #master db01 db01 [(none)]>show master status; +------------------+----------+--------------+------------------+------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+------------------------------------------+ | mysql-bin.000004 | 194 | | | 6aeade62-3621-11eb-b83c-000c294bdbec:1-4 | +------------------+----------+--------------+------------------+------------------------------------------+ 1 row in set (0.00 sec) #2、刷新3次日志 db01 [(none)]>flush logs; db01 [(none)]>flush logs; db01 [(none)]>flush logs; db01 [(none)]>show master status; +------------------+----------+--------------+------------------+------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+------------------------------------------+ | mysql-bin.000007 | 194 | | | 6aeade62-3621-11eb-b83c-000c294bdbec:1-4 | +------------------+----------+--------------+------------------+------------------------------------------+ 1 row in set (0.00 sec) #3、查看binlog_server #node4 [root@node4 binlog_server]# pwd /binlog_server [root@node4 binlog_server]# ll total 16 -rw-r----- 1 root root 241 Dec 6 21:10 mysql-bin.000004 -rw-r----- 1 root root 241 Dec 6 21:10 mysql-bin.000005 -rw-r----- 1 root root 241 Dec 6 21:10 mysql-bin.000006 -rw-r----- 1 root root 194 Dec 6 21:10 mysql-bin.000007
主库宕机,binlogserver 自动停掉,manager 也会自动停止。 处理思路: 1、通过binlog_server中的binlog日志来补偿新主库的数据缺失 2、新主库数据补偿完毕后,清除binlog_server上的原binlog文件 3、重新获取新主库的binlog到binlogserver中 4、重新配置文件binlog server信息 4、最后再启动MHA
1、binlog_server的mysql版本最好与主库一致,建议5.7 2、binlog_server备份目录必须与主库的binlog存放目录不一样 3、binlog_server永远不能提升为master,建议binlog_server独立部署 4、必须进入binlog_server备份目录拉取日志 5、必须在第一次拉取完日志后,再重启MHA服务 6、每次MHA只要做了故障的切换那么binlog-server就需要删除本地的binlog文件,并重新指定新的master重新获取新主库的binlog