MHA介绍及组成
MHA介绍
MHA能够在较短的时间内实现自动故障检测和故障转移,通常在10-30秒以内;在复制框架中,MHA能够很好地解决复制过程中的数据一致性问题,由于不需要在现有的replication中添加额外的服务器,仅需要一个manager节点,而一个Manager能管理多套复制,所以能大大地节约服务器的数量;另外,安装简单,无性能损耗,以及不需要修改现有的复制部署也是它的优势之处。
MHA还提供在线主库切换的功能,能够安全地切换当前运行的主库到一个新的主库中(通过将从库提升为主库),大概0.5-2秒内即可完成。
MHA的组成部分
1 2 3 4 5 `MHA Manager(管理节点)` 可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave上。 `MHA Node(数据节点)` 运行在每台MySQL服务器上 MHA Manager 会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master;然后将所有其他的slave重新指向新的master,整个故障转移过程对应用程序是完全透明的;
MHA软件结构介绍
节点信息
软件组件
作用介绍
MHA Manager(管理节点)
masterha_manger
用于启动MHA
masterha_check_ssh
用于检查MHA的SSH配置互信状况
masterha_check_repl
用于检查MySQL复制状态,以及配置信息
masterha_master_monitor
用于检测master是否宕机
masterha_check_status
用于检测当前MHA运行状态
masterha_master_switch
用于控制故障转移(自动或者手动)
masterha_conf_host
添加或删除配置的server信息
MHA Node(数据节点)
save_binary_logs
保存和复制master的二进制日志
apply_diff_relay_logs
识别差异的中继日志事件并将其差异的事件应用于其他slave
purge_relay_logs
清除中继日志(不会阻塞SQL线程)
MHA的工作的原理
:dango:MHA的设计原理分析(Failover 过程)
1.MHA软件启动
根据启动命令,分析MHA软件启动原理:
1 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 &
根据以上启动命令,需要先调取MHA启动脚本文件masterha_manager
,
--conf=.../app1.cnf
会根据加载的MHA的配置文件不同,实现管理多个高可用架构环境,进行高可用业务的架构环境的区分;
--remove_dead_master_conf
参数表示在主节点出现宕机情况时,将会从集群中被踢出,即从配置文件中删除掉故障节点;
--ignore_last_failover
默认MHA服务是不能频繁进行故障切换的,需要有一定的间隔时间,加此参数表示忽略切换的间隔时间;
/var/log/mha/app1/manager.log 2>&1
最后将MHA启动运行的信息放入到日志文件中即可
:dango:补充
1 2 3 4 5 6 7 8 9 10 11 补充说明:--ignore_last_failover 【官方解释】 If the previous failover failed, MHA does not start failover because the problem might happen again. The normal step to start failover is manually remove failover error file which is created under (manager_workdir)/(app_name).failover.error .By setting --ignore_last_failover, MHA continues failover regardless of the last failover status. 如果上一次高可用功能失败,MHA不会再启动高可用功能,因为这个问题可能会再次出现。后续再想启动故障转移的正常步骤是手动删除故障转移错误文件,错误文件会在manager_workdir目录下,创建一个名为app_name.failover.error的文件。对于设置--ignore_last_failover,表示无论上次故障切换状态如何,MHA都会继续进行启动故障切换功能 在缺省情况下,如果 MHA 检测到连续发生宕机,且两次宕机间隔不足 8 小时的话,则不会进行 Failover;之所以这样限制是为了避免 ping-pong 效应。该参数代表忽略上次 MHA 触发切换产生的文件;默认情况下,MHA 发生切换后会在日志记录,在日志目录中会生成 app1.failover.complete 文件;下次再次切换的时候如果发现该目录下存在该文件将不允许触发切换,除非在第一次切换后删除该文件; `官方默认8小时之内不能再次执行切换主库,除非删除锁文件 设置的工作目录下的*.failover.error文件`
2.MHA实现监控
利用MHA启动脚本文件masterha_manager
会自动调用监控脚本文件masterha_master_monitor
,并且每隔配置文件指定时间;
ping_interval=2
进行脚本监控一次,从而判断主节点是否处于存活状态,连续4次还没有主库心跳,即说明主库宕机;
wiki 1 2 3 4 5 6 7 8 # 监控脚本验证主节点存活方法 [root@xiaoQ-03 ~]# mysql -umha -pmha -h192.168.30.101 -e "select user();" mysql: [Warning] Using a password on the command line interface can be insecure. +-----------------+ | user() | +-----------------+ | mha@172.16.1.51 | +-----------------+
3.MHA选主过程
在MHA中进行选主时,根据选主源码文件信息分析,主要会利用到四个数组:alive latest pref bad,并且会识别节点编号信息;
在进行选主时,主要会关注竞选新主节点的日志量、以及是否设置candidate_master参数配置信息;
数组信息
简述
作用说明
alive
存活数组
主要用于探测存活的节点状态;当主库宕机后,探测的就是两个从库节点
latest
最新数组
表示获取日志最新的从库信息,即数据量最接近主库的从库(根据GTID信息 或 position信息)
pref
备选数组
在数组中具有candidate_master参数判断条件,此参数可以放入配置文件节点中,便于节点优先选择为新主
bad
不选数组
如果设定了参数:no_master=1,表示相应节点不参与竞选主; 如果设定了参数:log_bin=0(二进制日志没开),表示相应节点不参与竞选主; 如何设定了参数:check_slave_delay,检查从库延迟主库100M数据信息日志量,表示节点不参与竞选主
MHA选主判断总结(利用if判断选主的情况)
循环对比latest数组和pref数组的slave,如果存在相同的slave,并且这个slave不在bad数组当中,该slave会被推选为新的master
DB02节点即满足latest数组信息,又满足perf数组信息,但不满足bad数据信息,即会被选为新主,有多个按照号码顺序选举;
如果pref和bad数组当中的个数为0,则选择latest数组当中的第一个slave为master;
DB02节点没有candidate_master参数配置,又没有不选数组里的三种情况配置,即db02恰好是latest,为新主;
循环对比alive数组和pref数组当中的slaves,如果有一个slave相同,并且不在bad数组当中,该节点就会成为新的master;
DB02节点即不满足latest,也不满足bad,但是满足pref,也会被选择作为新主;
循环latest数组,如果又循环到slave不在bad数组当中,这个slave就会成为master,就算添加了candidate_master=1参数;
该slave也不一定会成为主库;
DB02节点即满足latest数组,不是bad数组,也会成为新的主;
从活着的slave当中进行循环,如果循环到slave不在bad数组当中,那么这个slave就会成为主库;
DB02节点是活着的,不满足bad,也可以成为新的主;
如果进行了多次选择都找不到主库,那么主库选择失败,failover失败;
选主策略简述表:
优先级
alive数组
latest数组
pref数组
bad数组
选主策略
多个选择情况
01
满足
满足
满足
不满足
优选选择
按照节点号码顺序选择
02
满足
满足
不满足
不满足
优选选择
按照节点号码顺序选择
03
满足
不满足
满足
不满足
优选选择
按照节点号码顺序选择
04
满足
不满足
不满足
不满足
优选活着节点
按照节点号码顺序选择
说明:在进行手工指定切换新主时,即应用了prio_new_master_host参数信息时,会最优先选择相应节点为新主;
一般情况下是:根据mha配置文件里server后的数值小的切换
1 2 3 4 5 6 [server1] hostname=10.0.0.51 port=3306 [server2] hostname=10.0.0.52 port=3306
4.MHA数据补偿
在进行数据补偿之前,需要让新主库与原有宕机主库进行对比,获悉需要补偿的数据量情况,即对比差的数据日志量信息;
然后可以从binlog日志中,进行补充数据信息的截取,随之进行数据信息补偿,但是有种特殊情况,若原有主库无法访问了;
所以进行数据补偿操作,也需要分各种情景进行处理:
原主库SSH连接正常:
各个从节点自动调用:save_binary_logs
脚本文件,立即保存缺失部分的bin_log,到各节点/var/tmp/目录;
原主库SSH连接异常:
各个从节点自动调用:apply_diff_relay_logs
脚本文件,进行relay_log日志差异信息补偿;
额外特殊数据补充:(利用主库日志冗余机制)
MHA提供了binlog_server功能,可以实时拉取主库的binlog日志到备份节点,从而进行数据额外补偿;
5.MHA业务切换
自动解除原有的主从关系,实现新的主从关系的建立;
wiki 1 2 3 4 5 6 # 所有从库解除主从关系操作 stop slave; reset slave; # 所有从库重构主从关系操作 change master to ...
6.MHA应用透明
实现MHA的VIP功能,利用脚本实现,上传mha_script.tar文件到/usr/local/bin目录中,然后进行解压处理;
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 # 上传MHA所需的脚本文件 [root@xiaoQ-03 ~]# cd /usr/local/bin/ [root@xiaoQ-03 bin]# chmod +x /usr/local/bin/* # 修改MHA脚本文件的信息 [root@xiaoQ-03 bin]# cp master_ip_failover master_ip_failover.bak [root@xiaoQ-03 bin]# dos2unix /usr/local/bin/* [root@xiaoQ-03 bin]# vim master_ip_failover 13 my $vip = '192.168.30.110/24'; 14 my $key = '1'; 15 my $if = 'eth0'; 16 my $ssh_start_vip = "/sbin/ifconfig $if:$key $vip"; 17 my $ssh_stop_vip = "/sbin/ifconfig $if:$key down"; 18 my $ssh_Bcast_arp= "/sbin/arping -I $if -c 3 -A 192.168.30.110"; # 修改配置文件 [root@xiaoQ-03 ~]# vim /etc/mha/app1.cnf master_ip_failover_script=/usr/local/bin/master_ip_failover # 重启MHA服务 [root@xiaoQ-03 bin]# masterha_stop --conf=/etc/mha/app1.cnf [root@xiaoQ-03 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 & # 手工在主库上添加VIP [root@xiaoQ-03 bin]# masterha_check_status --conf=/etc/mha/app1.cnf app1 (pid:103046) is running(0:PING_OK), master:192.168.30.101 -- 核实此时的MHA的主库节点 ifconfig eth0:1 192.168.30.110/24 -- 在主库节点手工添加vip地址信息 # 进行VIP地址连接测试 -- 可以使用navcat软件,连接MHA的vip地址,查看所连主机信息是否为主节点,当故障转移后可以核实VIP地址是否持续连接;
说明:进行MHA的VIP地址漂移时,只能在局域网环境进行漂移,不能实现跨网段的VIP地址漂移;
7.MHA故障报警
实现MHA的报警功能,利用脚本实现,上传mha_script.tar文件到/usr/local/bin目录中,然后进行解压处理;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 [root@xiaoQ-03 bin]# cp send_report send_report.bak 28 my $smtp ='smtp.qq.com' ; -- smtp服务器地址域名 29 my $mail_from ='330882721@qq.com' ; -- 发件箱信息配置 30 my $mail_user ='330882721' ; -- 用户名 QQ号 31 my $mail_pass ='ypokkranqlgkcbba' ; -- 邮箱授权码 32 my $mail_to ='330882721@qq.com' ; or my $mail_to =['to1@qq.com' ,'to2@qq.com' ]; -- 收件箱信息配置 [root@xiaoQ-03 ~]# vim /etc/mha/app1.cnf report_script=/usr/local/bin/send_report [root@xiaoQ-03 bin]# masterha_stop --conf=/etc/mha/app1.cnf [root@xiaoQ-03 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 &
8.MHA额外补偿
利用binlog_server作为额外的日志补偿的冗余方案,即实时保存主库的bin_log日志文件到特定节点目录中;
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 [root@xiaoQ-03 ~]# mkdir -p /data/binlog_server/ [root@xiaoQ-03 ~]# chown -R mysql.mysql /data/* [root@xiaoQ-03 ~]# cd /data/binlog_server [root@xiaoQ-03 binlog_server]# mysql -e "show slave status\G" |grep "Master_Log" Master_Log_File: mysql-bin.000002 Read_Master_Log_Pos: 1201 Relay_Master_Log_File: mysql-bin.000002 Exec_Master_Log_Pos: 1201 -- 拉取日志的起点,需要按照目前从库的已经获取到的二进制日志点为起点 [root@xiaoQ-03 binlog_server]# mysqlbinlog -R --host=192.168.30.101 --user=mha --password=mha --raw --stop-never mysql-bin.000002 & [root@xiaoQ-03 ~]# vim /etc/mha/app1.cnf [binlog1] no_master=1 -- 不存于竞选 hostname=192.168.30.103 -- 将日志额外补偿到哪个主机上 master_binlog_dir=/data/binlog_server/ -- 日志额外补偿的存储目录 [root@xiaoQ-03 bin]# masterha_stop --conf=/etc/mha/app1.cnf [root@xiaoQ-03 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 &
MHA搭建
环境一览
主机名
WanIP
LanIP
角色
mha
10.0.0.50
172.16.1.50
MHA管理端
db01
10.0.0.51
172.16.1.51
暂时主库,客户端
db02
10.0.0.52
172.16.1.52
从库,MHA客户端
db03
10.0.0.53
172.16.1.53
从库,MHA客户端
db04
10.0.0.54
172.16.1.54
从库,MHA客户端
MHA的必要条件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 1.主从复制OK 2.数据库的每个节点都得有rep主从复制用户 3.数据库每个节点要有mha用户 4.关闭自动删除relay-log 5.每一台都需要做免密连接 6.做mysqld软链接 mysql> set global read_only=1; mysql> set global relay_log_purge = 0;
:dango:主从复制
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 [root@db01 ~]# vim /etc/my.cnf [mysqld] basedir=/app/mysql datadir=/app/mysql/data server_id=1 log-bin=mysql-bin skip_name=resolve relay_log_purge=0 mysql> grant replication slave on *.* to rep@'172.16.1.5%' identified by '123' ; db01 [(none)]>show master status; +------------------+----------+--------------+ | File | Position | Binlog_Do_DB | +------------------+----------+--------------+ | mysql-bin.000003 | 327 | | +------------------+----------+--------------+ change master to master_host='172.16.1.51' , master_user='rep' , master_password='123' , master_log_file='mysql-bin.000003' , master_log_pos=327, master_port=3306; mysql > start slave;
:dango:主库执行
1 2 3 4 5 6 mysql> grant replication slave on *.* to rep@'172.16.1.5%' identified by '123' ; mysql> grant all on *.* to mha@'172.16.1.5%' identified by 'mha' ;
:dango:互信免密
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 [root@db01 ~]# cat push_public_key.sh yum -y install sshpass test -f ~/.ssh/id_rsa || ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa >/dev/null 2>&1for ip in 50 51 52 53 54;do ping -c1 -W1 172.16.1.$ip &>/dev/null [ $? -eq 0 ] &&\ sshpass -p 1 ssh-copy-id -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa.pub root@172.16.1.$ip &>/dev/null &&\ echo "172.16.1.$ip 推送成功..." ||\echo "172.16.1.$ip 推送失败..." done [root@db01 ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1 [root@db02 ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1 [root@db03 ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1 [root@db04 ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1 [root@mha-manager ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1 [root@db01 ~]# sshpass -p 1 ssh-copy-id -i ~/.ssh/id_dsa.pub root@172.16.1.50 [root@db01 ~]# sshpass -p 1 ssh-copy-id -i ~/.ssh/id_dsa.pub root@172.16.1.51 [root@db01 ~]# sshpass -p 1 ssh-copy-id -i ~/.ssh/id_dsa.pub root@172.16.1.52 [root@db01 ~]# sshpass -p 1 ssh-copy-id -i ~/.ssh/id_dsa.pub root@172.16.1.53 [root@db01 ~]# sshpass -p 1 ssh-copy-id -i ~/.ssh/id_dsa.pub root@172.16.1.54
:dango:命令软链接
1 2 3 4 5 6 7 8 9 10 11 [root@db01 ~]# ln -s /app/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog [root@db01 ~]# ln -s /app/mysql/bin/mysql /usr/bin/mysql [root@db02 ~]# ln -s /app/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog [root@db02 ~]# ln -s /app/mysql/bin/mysql /usr/bin/mysql [root@db03 ~]# ln -s /app/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog [root@db03 ~]# ln -s /app/mysql/bin/mysql /usr/bin/mysql [root@db04 ~]# ln -s /app/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog [root@db04 ~]# ln -s /app/mysql/bin/mysql /usr/bin/mysql
部署MHA客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [root@db01 ~]# wget http://test.driverzeng.com/MySQL_plugins/mha4mysql-node-0.56-0.el6.noarch.rpm [root@db01 ~]# wget https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-node-0.58-0.el7.centos.noarch.rpm [root@db01 ~]# scp mha4mysql-node-0.56-0.el6.noarch.rpm 10.0.0.50:/root [root@db01 ~]# scp mha4mysql-node-0.56-0.el6.noarch.rpm 10.0.0.52:/root [root@db01 ~]# scp mha4mysql-node-0.56-0.el6.noarch.rpm 10.0.0.53:/root [root@db01 ~]# scp mha4mysql-node-0.56-0.el6.noarch.rpm 10.0.0.54:/root [root@db01 ~]# yum -y localinstall mha4mysql-node-0.56-0.el6.noarch.rpm [root@db02 ~]# yum -y localinstall mha4mysql-node-0.56-0.el6.noarch.rpm [root@db03 ~]# yum -y localinstall mha4mysql-node-0.56-0.el6.noarch.rpm [root@db04 ~]# yum -y localinstall mha4mysql-node-0.56-0.el6.noarch.rpm [root@mha ~]# yum -y localinstall mha4mysql-node-0.56-0.el6.noarch.rpm
部署MHA管理端
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 [root@mha-manager ~]# mkdir /etc/mha [root@mha-manager ~]# vim /etc/mha/app1.cnf [server default] manager_log=/etc/mha/logs/manager.log manager_workdir=/etc/mha/app1 master_binlog_dir=/app/mysql/data user=mha password=mha ping_interval=2 repl_user=rep repl_password=123 ssh_user=root ssh_port=22 [server1] hostname=172.16.1.51 port=3306 [server2] hostname=172.16.1.52 port=3306 [server3] hostname=172.16.1.53 port=3306 [server4] hostname=172.16.1.54 port=3306 mysql> grant all on *.* to mha@'172.16.1.5%' identified by 'mha' ; [root@mha-manager ~]# mkdir -p /etc/mha/{logs,app1} [root@mha-manager ~]# ll /etc/mha/ total 4 drwxr-xr-x 2 root root 6 Aug 27 12:20 app1 -rw-r--r-- 1 root root 457 Aug 27 12:16 app1.cnf drwxr-xr-x 2 root root 6 Aug 27 12:19 logs [root@mha-manager ~]# masterha_check_ssh --conf=/etc/mha/app1.cnf All SSH connection tests passed successfully. [root@mha-manager ~]# masterha_check_repl --conf=/etc/mha/app1.cnf MySQL Replication Health is OK. nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/logs/manager.log 2>&1 &`masterha_manager:`启动命令 --conf=/etc/mha/app1.cnf:指定配置文件 --remove_dead_master_conf:做完切换后,从配置文件中摘除宕机的主库 --ignore_last_failover:忽略上一次切换 1.MHA在做一次切换后,生成一个锁文件(app1.failover.complete),在工作目录下,8个小时之内,无法做第二次切换 2.MHA切换完成后,会自动结束MHA的进程 3.在所有从库数据相同时,MHA会选择配置文件中标签id 最小的切换 [root@mha-manager ~]# masterha_check_status --conf=/etc/mha/app1.cnf app1 (pid:19524) is running(0:PING_OK), master:172.16.1.51 [root@mha-manager ~]# vim /usr/lib/systemd/system/mha.service [Unit] Description=MHA After=network.target sshd-keygen.service Wants=sshd-keygen.service [Service] Type=sample ExecStart=/usr/bin/masterha_manager --conf=/etc/mha/app1.cnf -- remove_dead_master_conf --ignore_last_failover > /etc/mha/logs/manager.log ExecStop=/usr/bin/masterha_stop --conf=/etc/mha/app1.cnf [Install] WantedBy=multi-user.target
MHA配置文件详解:dango:
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 [server default] manager_workdir=/var/log/masterha/app1 manager_log=/var/log/masterha/app1/manager.log master_binlog_dir=/data/mysql master_ip_failover_script= /usr/local/bin/master_ip_failover master_ip_online_change_script= /usr/local/bin/master_ip_online_change password=1 user=root ping_interval=1 remote_workdir=/tmp repl_password=123 repl_user=rep report_script=/usr/local/send_report secondary_check_script= /usr/local/bin/masterha_secondary_check -s server03 -s server02 --user=root --master_host=server02 --master_ip=192.168.0.50 --master_port=3306 shutdown_script="" ssh_user=root [server1] hostname=10.0.0.51 port=3306 [server2] hostname=10.0.0.52 port=3306 candidate_master=1 check_repl_delay=0 secondary_check_script= /usr/local/bin/masterha_secondary_check -s server03 -s server02 --user=root --master_host=server02 --master_ip=192.168.0.50 -- master_port=3306 shutdown_script="" ssh_user=root [server1] hostname=10.0.0.51 port=3306 [server2] hostname=10.0.0.52 port=3306 candidate_master=1 check_repl_delay=0
切换日志–注意几点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 GTID failover mode = 0 Starting Non-GTID based failover. master_ip_failover_script is not set . Skipping invalidating dead master IP address. Candidate masters from the configuration file: Non-candidate masters: candidate_master=1 // 设立太子,但是如果太子落后其他机器数据超过100M,就废储 check_repl_delay=0 // 关闭对太子落后的检测 All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='172.16.1.54' , MASTER_PORT=3306,MASTER_LOG_FILE='mysql-bin.000003' , MASTER_LOG_POS=878597, MASTER_USER='rep' ,MASTER_PASSWORD='xxx' ;
MHA相关工具命令
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 save_binary_logs --command =save --start_file=mysql-bin.000001 --start_pos=878597 --binlog_dir=/app/mysql/data -- output_file=/var/tmp/saved_master_binlog_from_172.16.1.52_3306_20240827154042.bi nlog --handle_raw_binlog=1 --disable_log_bin=0 --manager_version=0.58 pply_diff_relay_logs --command =apply --slave_user='mha' --slave_host=172.16.1.54 --slave_ip=172.16.1.54 --slave_port=3306 -- apply_files=/var/tmp/saved_master_binlog_from_172.16.1.52_3306_20240827154042.bi nlog --workdir=/var/tmp --target_version=5.7.42-log --timestamp=20240827154042 --handle_raw_binlog=1 --disable_log_bin=0 --manager_version=0.58 --slave_pass=xxx
binlog的路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@db02 ~]# ll /var/tmp/saved_master_binlog_from_172.16.1.52_3306_20240827154042.binlog -rw-r--r-- 1 root root 177 Aug 27 15:40 /var/tmp/saved_master_binlog_from_172.16.1.52_3306_20240827154042.binlog [root@mha-manager ~]# ll /etc/mha/app1/saved_master_binlog_from_172.16.1.52_3306_20240827154042.binlog -rw-r--r-- 1 root root 177 Aug 27 15:40 /etc/mha/app1/saved_master_binlog_from_172.16.1.52_3306_20240827154042.binlog [root@db04 ~]# ll /var/tmp/saved_master_binlog_from_172.16.1.52_3306_20240827154042.binlog -rw-r--r-- 1 root root 177 Aug 27 15:40 /var/tmp/saved_master_binlog_from_172.16.1.52_3306_20240827154042.binlog
MHA自动恢复
手动恢复
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [root@db02 ~]# systemctl start mysqld CHANGE MASTER TO MASTER_HOST='172.16.1.54' , MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000003' , MASTER_LOG_POS=878597, MASTER_USER='rep' , MASTER_PASSWORD='123' ; mysql> start slave; [root@mha-manager ~]# vim /etc/mha/app1.cnf [server2] hostname=172.16.1.52 port=3306 [root@mha-manager ~]# systemctl start mha [root@mha-manager ~]# masterha_check_status --conf=/etc/mha/app1.cnf
自动恢复脚本
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 #!/bin/bash . /etc/init.d/functions log_file='/etc/mha/logs/manager.log' mha_conf="/etc/mha/app1.cnf" repl_pass='123' mha_user=$(awk -F= '/^user/{print $2}' ${mha_conf} ) mha_password=$(awk -F= '/^password/{print $2}' ${mha_conf} ) down_master=$(sed -nr 's#^Master (.*)\(.*\).*!$#\1#gp' ${log_file} |tail -1 ) change_master=$(grep -i 'change master to' ${log_file} |tail -1|awk -F: '{print $4}' |sed "s#xxx#${repl_pass} #g" ) master_ip_failover_script=/etc/mha/app1/master_ip_failover ssh ${down_master} 'systemctl start mysqld' while true ;do mysqladmin -u${mha_user} -p${mha_password} -h${down_master} ping &>/dev/null if [ $? -eq 0 ];then mysql -u${mha_user} -p${mha_password} -h${down_master} -e "${change_master} ;start slave" break fi done cat > ${mha_conf} <<EOF [server default] manager_log=/etc/mha/logs/manager.log manager_workdir=/etc/mha/app1 master_binlog_dir=/app/mysql/data password=${mha_password} ping_interval=2 repl_password=123 repl_user=rep ssh_port=22 ssh_user=root user=${mha_user} [server1] hostname=172.16.1.51 port=3306 [server2] hostname=172.16.1.52 port=3306 [server3] hostname=172.16.1.53 port=3306 [server4] hostname=172.16.1.54 port=3306 EOF systemctl start mha while true ;do masterha_check_status --conf=${mha_conf} &>/dev/null if [ $? -eq 0 ];then action "mha server" /bin/true break fi done
优化
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 [root@mha ~]# cat failover_status last_new_master=$(grep '(new master)' /etc/mha/logs/manager.log |tail -2|awk -F '(' 'NR==1{print $1}' ) [root@mha ~]# cat recovery_mha.sh . /etc/init.d/functions . /root/failover_status log_file='/etc/mha/logs/manager.log' mha_conf="/etc/mha/app1.cnf" repl_pass='123' mha_user=$(awk -F= '/^user/{print $2}' ${mha_conf} ) mha_password=$(awk -F= '/^password/{print $2}' ${mha_conf} ) down_master=$(sed -nr 's#^Master (.*)\(.*\).*!$#\1#gp' ${log_file} |tail -1 ) while true ;do if [ ${down_master} == ${last_new_master} ];then change_master=$(grep -i 'change master to' ${log_file} |tail -1|awk -F: '{print $4}' |sed "s#xxx#${repl_pass} #g" ) echo "主库修复中..." ssh ${down_master} -C 'systemctl start mysqld' while true ;do mysqladmin -u${mha_user} -p${mha_password} -h${down_master} ping &>/dev/null if [ $? -eq 0 ];then mysql -u${mha_user} -p${mha_password} -h${down_master} -e "${change_master} ;start slave" echo "主库修复成功..." break fi done echo "正在补全MHA配置文件..." cat > ${mha_conf} <<- EOF [server default] manager_log=/etc/mha/logs/manager.log manager_workdir=/etc/mha/app1 master_binlog_dir=/app/mysql/data password=${mha_password} ping_interval=2 repl_password=123 repl_user=rep ssh_port=22 ssh_user=root user=${mha_user} [server1] hostname=172.16.1.51 port=3306 [server2] hostname=172.16.1.52 port=3306 [server3] hostname=172.16.1.53 port=3306 [server4] hostname=172.16.1.54 port=3306 EOF echo "正在启动MHA..." systemctl start mha while true ;do masterha_check_status --conf=${mha_conf} &>/dev/null if [ $? -eq 0 ];then action "MHA manager启动" /bin/true exit 0 fi done else continue fi done
MHA的vip漂移
配置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 [root@mha-manager ~]# vim /etc/mha/app1.cnf [server default] master_ip_failover_script=/etc/mha/app1/master_ip_failover [root@mha-manager ~]# vim /etc/mha/app1/master_ip_failover my $vip = '172.16.1.55/24' ; my $key = '1' ; my $ssh_start_vip = "/sbin/ifconfig eth1:$key $vip " ; my $ssh_stop_vip = "/sbin/ifconfig eth1:$key down" ; [root@mha-manager ~]# chmod +x /etc/mha/app1/master_ip_failover [root@db01 ~]# ifconfig eth1:1 172.16.1.55/24 [root@mha-manager ~]# systemctl stop mha [root@mha-manager ~]# systemctl start mha 1.脚本权限问题 [root@mha-manager ~]# chmod +x /etc/mha/app1/master_ip_failover 2.脚本语法问题 3.脚本格式问题 [root@mha-manager ~]# dos2unix /etc/mha/app1/master_ip_failover dos2unix: converting file /etc/mha/app1/master_ip_failover to Unix format ...
自动恢复脚本
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 [root@mha ~]# cat failover_status last_new_master=$(grep '(new master)' /etc/mha/logs/manager.log |tail -2|awk -F '(' 'NR==1{print $1}' ) [root@mha ~]# cat recovery_mha.sh . /etc/init.d/functions . /root/failover_status log_file='/etc/mha/logs/manager.log' mha_conf="/etc/mha/app1.cnf" repl_pass='123' mha_user=$(awk -F= '/^user/{print $2}' ${mha_conf} ) mha_password=$(awk -F= '/^password/{print $2}' ${mha_conf} ) down_master=$(sed -nr 's#^Master (.*)\(.*\).*!$#\1#gp' ${log_file} |tail -1 ) while true ;do if [ ${down_master} == ${last_new_master} ];then change_master=$(grep -i 'change master to' ${log_file} |tail -1|awk -F: '{print $4}' |sed "s#xxx#${repl_pass} #g" ) echo "主库修复中..." ssh ${down_master} -C 'systemctl start mysqld' while true ;do mysqladmin -u${mha_user} -p${mha_password} -h${down_master} ping &>/dev/null if [ $? -eq 0 ];then mysql -u${mha_user} -p${mha_password} -h${down_master} -e "${change_master} ;start slave" echo "主库修复成功..." break fi done echo "正在补全MHA配置文件..." cat > ${mha_conf} <<- EOF [server default] master_ip_failover_script=/etc/mha/app1/master_ip_failover manager_log=/etc/mha/logs/manager.log manager_workdir=/etc/mha/app1 master_binlog_dir=/app/mysql/data password=${mha_password} ping_interval=2 repl_password=123 repl_user=rep ssh_port=22 ssh_user=root user=${mha_user} [server1] hostname=172.16.1.51 port=3306 [server2] hostname=172.16.1.52 port=3306 [server3] hostname=172.16.1.53 port=3306 [server4] hostname=172.16.1.54 port=3306 EOF echo "正在启动MHA..." systemctl start mha while true ;do masterha_check_status --conf=${mha_conf} &>/dev/null if [ $? -eq 0 ];then action "MHA manager启动" /bin/true exit 0 fi done else continue fi done
MySQL binlog实时同步
使用mysqlbinlog实时同步binlog
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 [root@mha-manager ~]# vim /etc/mha/app1.cnf [binlog1] no_master=1 hostname=172.16.1.50 master_binlog_dir=/data/mysql/binlog/ [root@mha-manager ~]# mkdir -p /data/mysql/binlog/ [root@mha-manager ~]# cat /etc/yum.repos.d/mysql-community.repo [mysql56-community] name=MySQL 5.6 Community Server baseurl=http://repo.mysql.com/yum/mysql-5.6-community/el/7/$basearch enabled=1 gpgcheck=0 [root@mha-manager binlog]# yum install -y mysql [root@mha-manager binlog]# mysqlbinlog -R --host=172.16.1.55 --user=mha --password=mha --raw --stop-never mysql-bin.000001 &