二十二、Mysql之MHA

一、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(第二版)》)。

二、MHA的工作原理

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

2、Node工具包主要包括以下几个工具:

save_binary_1ogs         #保存宕机的master的binlog
apply_diff_relay_logs    #识别relay log的差异并应用于其它从节点
filter_mysqlbinlog       #防止回滚事件一MHA已不再使用这个工具
purge_relay_logs         #清除中继日志一不会阻塞SQL线程

四、部署MHA

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主从。

2、拓扑图架构图

 

3、db01、db02、db03二进制部署mysql5.7

详细部署步骤: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

4.2连个从库my.cnf配置

#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

4.3主库创建主从复制授权用户

#mater db01
[root@db01 ~]# mysql -uroot 
db01 [(none)]>grant replication slave on *.* to repl@'10.0.0.%' identified by '123';

4.4所有从库配置change master to参数

 
#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
......

4.5所有数据库配置关闭relaylog自动删除

 
#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

5.1MHA安装包

mha4mysql-manager-0.56-0.el6.noarch.rpm
mha4mysql-node-0.56-0.el6.noarch.rpm

5.2所有节点安装安装mha node

#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

5.3主库上添加mha管理账号(主库会自动同步到从库)

#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)

5.4.创建软连接(所有节点)

#如果不创建命令软连接,检测mha复制情况的时候会报错
ln -s /app/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
ln -s /app/mysql/bin/mysql /usr/bin/mysql

#MHA源码包中设置的mysqlbinlog和mysql的默认路径为/usr/bin

6、在node4上安装MHA Manager

这里以单独的机器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

6.2创建Manager必须的目录

#node4
mkdir -p /etc/mha #创建必须目录
mkdir -p /var/log/mha/app1 #创建日志,目录可以管理多套主从复制

6.3创建mha配置文件

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

6.4MHA 配置文件详解

 
[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

7、配置ssh信任(所有节点)

#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、在MHA管理器上使用mha自带的工具来测试ssh和主从复制

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.

8.2测试主从复制

[root@node4 app]# masterha_check_repl --conf=/etc/mha/app1.cnf
最后提示MySQL Replication Health is OK.则主从正常

9、启动MHA

经过上面的部署过后,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 ~]# 

5.2在mha manager主机node4上查看mha日志

#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成为了新的主库

5.3查看db02和db03的slave状态

#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建立的主从关系

5.4查看mha信息

原主库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

在原db01宕机后,db01的配置信息[server1]也被从配置文件中自动移除。

 
[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

六、MHA故障恢复

原主库恢复后,只能为当时主库的从库。

6.1恢复故障的数据库db01

1、数据库故障不严重,不需要重做部署数据库或初始化数据库,可以直接重新建议新的主从关系。
2、数据库物理损坏严重,恢复数据库时,需要使用新数据库的全备来做恢复,然后再建立新的主从关系。

6.2原主库db01与新主库db02建立主从

原主库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';

6.3启动原主库,添加change master to 信息与新主库建立主从

 
#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的主从建立完成

6.4恢复MHA的配置

恢复[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

6.5重新启动MHA

[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

此时db02为主库,db01和db03为从库。

 

七、设置VIP漂移

通过MHA自带的脚本实现master_ip_failover(vip、漂移、应用透明)

IP漂移的两种方式:

1、通过keepalived的方式,管理虚拟IP的漂移,需要配置漂移数据库的权重,避免keepalive漂移跟MHA漂移不一致问题。(不推荐使用)
2、通过MHA自带脚本方式,管理虚拟IP的漂移(强烈推荐)

7.1MHA漂移脚本

 
#!/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时的网卡名

该脚本为软件自带,脚本获取方法:再mha源码包中的samples目录下有该脚本的模板,对该模板进行修改即可使用。路径如:mha4mysql-manager-0.56/samples/scripts

 

7.2将MHA脚本上传到/usr/bin目录并添加执行权限

1、上传MHA脚本
2、[root@node4 bin]# chmod +x /usr/bin/master_ip_failover 

7.3添加MHA脚本

叫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

7.4主库上,手工生成第一个vip地址

 
#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)

7.5重启MHA

 
#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

7.6VIP漂移测试

现有主库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重新建立了主从

7.6.主从环境恢复

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-server

主库宕机,也许会造成主库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保存目录(不能和主库保存位置重复)

8.2在mha-manager(node4)上创建binlog_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文件最开始的位置

8.3重新启动MHA生效配置(必须等binlog拉取完才能启动mha)

#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 &

8.4测试binlog备份

 
#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

8.4故障处理

主库宕机,binlogserver 自动停掉,manager 也会自动停止。
处理思路:
1、通过binlog_server中的binlog日志来补偿新主库的数据缺失
2、新主库数据补偿完毕后,清除binlog_server上的原binlog文件
3、重新获取新主库的binlog到binlogserver中
4、重新配置文件binlog server信息
4、最后再启动MHA

8.5binlog_server注意事宜

 
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

 

posted @ 2020-12-06 21:46  yaowx  阅读(311)  评论(0编辑  收藏  举报