MHA高可用
1.准备三台机器
IP: 10.0.0.51 db01 2G
IP: 10.0.0.52 db02 2G
IP: 10.0.0.53 db03 2G
2.关闭防火墙
3.关闭selinux
一、MHA原理
1.基本原理
当Master出现故障时,它可以自动将最新数据的Slave提升为新的Master,然后将所有其他的Slave重新指向新的Master。
2.原理详解
1.保存master主库上面的所有binlog(node节点)
2.找到数据最新的从库(通过对比relay-log)
3.将数据最新的从库数据同步到其他从库
4.提升一个从库为主库(一般情况提升数据最新的,二般情况提升我们指定的从库为主库)
5.通过原来主库的binlog补全新的主库数据
6.其他从库以新的主库为主做主从复制
#问题:
1)如果主库是突然断电,怎么保存binlog
2)relay-log不是一直存在,当执行完一个sql会删除,怎么对比
3)从库开启binlog,但是并不写入数据,其他从库做主从时怎么同步数据

二、MHA架构

1.MHA属于C/S架构
2.manager尽量避免与master装在一起
3.一个MHA manager可以管理多套mysql主从集群
4.所有的机器都要安装node节点
5.MHA manager通过ssh去管理其他node节点,所以先做免密
6.MHA可以在mysql运行后添加,不影响mysql的使用
7.MHA manager管理其他机器的node节点,管理主库的node用来保存binlog,管理从库的node用来切换
三、MHA工具介绍
1.manager相关工具
#通过解压MHA源码包,查看工具
[root@db01 ~]# tar xf mha4mysql-manager-0.56.tar.gz
[root@db01 ~]# cd mha4mysql-manager-0.56/bin/
[root@db01 bin]# ll
#检查replicatin主从复制
masterha_check_repl
#检查ssh免密
masterha_check_ssh
#检查MHA启动状态
masterha_check_status
#配置主机信息
masterha_conf_host
[server_2]
hostname=10.0.0.52
port=3306
[server_3]
hostname=10.0.0.53
port=3306
#MHA manager启动程序
masterha_manager
#监控MHA主机
masterha_master_monitor
#切换主机
masterha_master_switch
#建立TCP连接
masterha_secondary_check
#停止MHA
masterha_stop
#常用的
masterha_check_repl
masterha_check_ssh
masterha_manager
masterha_stop
2.node节点相关工具
#通过解压MHA源码包,查看工具
[root@db01 ~]# tar xf mha4mysql-node-0.56.tar.gz
[root@db01 ~]# cd mha4mysql-node-0.56/bin/
[root@db01 bin]# ll
#对比relay-log,找出数据最新的从库
apply_diff_relay_logs
#防止主库切换过程中binlog事务还没有提交就回滚
filter_mysqlbinlog
#手动删除relay-log ####必须提前关闭relay-log自动删除的功能
purge_relay_logs
#保存binlog日志
save_binary_logs
四、MHA优点
1)Masterfailover and slave promotion can be done very quickly
自动故障转移快
2)Mastercrash does not result in data inconsistency
主库崩溃不存在数据一致性问题
3)Noneed to modify current MySQL settings (MHA works with regular MySQL)
不需要对当前mysql环境做重大修改
4)Noneed to increase lots of servers
不需要添加额外的服务器(仅一台manager就可管理上百个replication)
5)Noperformance penalty
性能优秀: 可工作在半同步复制和异步复制,当监控mysql状态时,仅需要每隔N秒向master发送ping包(默认3秒一次,默认三次),所以对性能无影响。你可以理解为MHA的性能和简单的主从复制框架性能一样。
#ping www.baidu.com (icmp协议)
#sql ping 检测主库是否存活
6)Works with any storage engine
只要replication支持的存储引擎,MHA都支持,不会局限于innodb
五、基于GTID的主从复制
1.什么是GTID?
1.他是一个事务标识符,唯一标识符
2.这个标识符不止是在执行的机器上是唯一的,在整个集群都是唯一的
3.GTID实际上是由 UUID+TID 组成的
UUID是数据库实例的标识符
TID表示事务提交的数量,会根据执行的事务数量增加
#形式:ee0c0c96-8756-11ea-9ab7-000c29f4ca5b:1
2.GTID优点
1.普通的主从复制需要记录binlog的名字和位置点,基于GTID的主从不需要记录,做主从的时候会自动查找
2.普通的主从复制是一个sql线程,基于GTID的主从是每个库,开启一个SQL线程
3.binlog记录方式,如果配置row模式,保存binlog,只保存修改的列,节省了磁盘空间和内存使用
4.GTID会把主从的相关信息记录到表中
5.支持延时复制
3.GTID缺点
1.mysqldump备份的时候,需要加一个参数 --set-gtid-purged=OFF 或者 --triggers --routines --events
2.如果主从复制SQL线程出现问题,可以跳过问题,但是基于GTID的主从跳过不了错误
1)传统主从跳过错误:
mysql> stop slave;
mysql> set global sql_slave_skip_counter=1;
mysql> start slave;
2)基于GTID跳过错误事务的方式:
4.基于GTID主从的搭建
1)配置主从配置
#主库db01:
[root@db01 bin]# vim /etc/my.cnf
[mysqld]
server_id=1
log_bin=mysql-bin
[root@db01 bin]# systemctl restart mysql
#从库db02:
[root@db01 bin]# vim /etc/my.cnf
[mysqld]
server_id=2
[root@db02 bin]# systemctl restart mysql
#从库db03:
[root@db01 bin]# vim /etc/my.cnf
[mysqld]
server_id=3
[root@db03 bin]# systemctl restart mysql
2)查看GTID是否启动
mysql> show variables like '%gtid%';
+---------------------------------+-----------+
| Variable_name | Value |
+---------------------------------+-----------+
| binlog_gtid_simple_recovery | OFF |
| enforce_gtid_consistency | OFF |
| gtid_executed | |
| gtid_mode | OFF |
| gtid_next | AUTOMATIC |
| gtid_owned | |
| gtid_purged | |
| simplified_binlog_gtid_recovery | OFF |
+---------------------------------+-----------+
8 rows in set (0.00 sec)
3)修改配置文件启动GTID
#配置三台主机开启GTID
1.主库db01
[root@db01 bin]# vim /etc/my.cnf
[mysqld]
server_id=1
log_bin=mysql-bin
gtid_mode=on
enforce_gtid_consistency
log-slave-updates
[root@db01 bin]# systemctl restart mysql
2.从库db02
[root@db02 ~]# vim /etc/my.cnf
[mysqld]
server_id=2
gtid_mode=on
enforce_gtid_consistency
log_bin=mysql-bin
log-slave-updates
[root@db01 bin]# systemctl restart mysql
3.从库db03
[root@db02 ~]# vim /etc/my.cnf
[mysqld]
server_id=3
gtid_mode=on
enforce_gtid_consistency
log_bin=mysql-bin
log-slave-updates
[root@db01 bin]# systemctl restart mysql
#扩展:配置log-slave-updates参数的情况
1.GTID主从
2.双主+keepalived(一般不使用,浪费资源)
3.级联复制
4)创建主从用户
mysql> grant replication slave on *.* to rep@'172.16.1.5%' identified by '123';
Query OK, 0 rows affected (0.00 sec)
5)从库执行change master to
change master to
master_host='172.16.1.51',
master_user='rep',
master_password='123',
master_auto_position=1;
6)启动IO线程和SQL线程
mysql> start slave;
mysql> show slave status\G
六、部署MHA
1.部署之前需要的操作
1.验证主从环境没有问题
2.主从都要配置关闭自动删除relay-log功能
#临时关闭
mysql> set global relay_log_purge=0;
#永久关闭
[root@db02 ~]# vim /etc/my.cnf
[mysqld]
relay_log_purge=0
[root@db02 ~]# systemctl restart mysql
3.从库可以设置只读(也可以不设置)
set global read_only=1;
2.部署MHA
1)安装依赖(所有服务器)
[root@db01 data]# yum install perl-DBD-MySQL -y
2)安装manager节点依赖(部署manager节点,10.0.0.53)
[root@db03 ~]# yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes
3)部署node节点(所有机器)
[root@db01 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm
[root@db02 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm
[root@db03 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm
4)部署manager节点(db03)
[root@db03 ~]# yum localinstall -y mha4mysql-manager-0.56-0.el6.noarch.rpm
5)添加一个MHA的管理用户(所有机器)
mysql> grant all on *.* to mha@'172.16.1.5%' identified by 'mha';
Query OK, 0 rows affected (0.00 sec)
mysql> select user,host,password from mysql.user;
+------+-------------+-------------------------------------------+
| user | host | password |
+------+-------------+-------------------------------------------+
| root | localhost | |
| mha | 172.16.1.5% | *F4C9AC49A736981AE2739FC2F4A1FD92B4F07929 |
+------+-------------+-------------------------------------------+
8 rows in set (0.00 sec)
#从库也要创建主从用户
grant replication slave on *.* to rep@'172.16.1.5%' identified by '123';
6)创建命令软连接
#如果不创建命令软连接,检测mha复制情况的时候会报错
[root@mysql-db01 ~]# ln -s /usr/local/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
[root@mysql-db01 ~]# ln -s /usr/local/mysql/bin/mysql /usr/bin/mysql
7)编写MHA配置文件(manager节点的机器)
#在安装manager节点的机器上,创建mha配置文件目录
[root@db03 ~]# mkdir /service/mha -p
#编辑配置文件
[root@db03 ~]# vim /service/mha/app1.cnf
[server default]
#日志存放路径
manager_log=/service/mha/manager.log
#定义工作目录
manager_workdir=/service/mha/app1
#定义binlog的存放目录
master_binlog_dir=/usr/local/mysql/data
#管理用户
user=mha
#管理用户的密码
password=mha
#检测主库心跳间隔时间
ping_interval=2
#主从复制的用户
repl_user=rep
#主从复制的密码
repl_password=123
#ssh免密登录的用户
ssh_user=root
[server1]
hostname=172.16.1.51
port=3306
[server2]
hostname=172.16.1.52
port=3306
[server3]
hostname=172.16.1.53
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
8)配置免密登录(每一台机器都要执行)
#创建秘钥对
[root@mysql-db01 ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1
#发送公钥,包括自己
[root@mysql-db01 ~]# ssh-copy-id -i /root/.ssh/id_dsa.pub root@172.16.1.51
[root@mysql-db01 ~]# ssh-copy-id -i /root/.ssh/id_dsa.pub root@172.16.1.52
[root@mysql-db01 ~]# ssh-copy-id -i /root/.ssh/id_dsa.pub root@172.16.1.53
9)检测MHA配置状态
1.使用mha命令检测ssh免密登录
[root@db03 ~]# masterha_check_ssh --conf=/service/mha/app1.cnf
2.使用mha命令检测主从状态
[root@db03 ~]# masterha_check_repl --conf=/service/mha/app1.cnf
10)启动MHA
[root@db03 ~]# nohup masterha_manager --conf=/service/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /service/mha/manager.log 2>&1 &
nohup #后台启动
masterha_manager #MHA启动程序
--conf=/service/mha/app1.cnf #指定配置文件
--remove_dead_master_conf #从配置文件里移除已经宕机的主机标签
--ignore_last_failover #忽略最后一次切换
< /dev/null > /service/mha/manager.log 2>&1 &
1)测试切换主机
#停掉主机数据库
[root@db01 ~]# systemctl stop mysql
#去从库查看
11.修复MHA中故障的主库
1.修复主机,启动数据库
2.去MHA日志中找到change master to 语句
[root@db03 ~]# grep -i 'change master to' /service/mha/manager.log
Thu Apr 30 10:48:53 2020 - [info] All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='172.16.1.52', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='rep', MASTER_PASSWORD='xxx';
3.到重新修复的mysql主机,执行同步命令(修改xxx为密码)
mysql> CHANGE MASTER TO MASTER_HOST='172.16.1.52', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='rep', MASTER_PASSWORD='123';
Query OK, 0 rows affected, 2 warnings (0.02 sec)
4.启动线程
start slave;
5.将主机信息重新添加到MHA的配置文件中
[server1]
hostname=172.16.1.51
port=3306
6.重新启动MHA
[root@db03 ~]# nohup masterha_manager --conf=/service/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /service/mha/manager.log 2>&1 &
12.主库自动拉起脚本
1.先配置一个所有数据库都存活时的MHA配置
[root@db03 mha]# cp app1.cnf app11.cnf
2.配置脚本
[root@db01 ~]# vim recover.sh
#判断数据是否挂掉
mysqlpid=`ps -ef | grep [m]ysql | wc -l`
#启动数据库
if [ mysqlpid -eq 0 ]
systemctl start mysql
else
pkill mysqld
systemctl start mysql
fi
sleep 3
#获取change mater to 内容
change=`ssh 172.16.1.53 "grep -i 'change master to' /service/mha/manager.log | cut -d ':' -f 4 | sed 's#xxx#123#g'"`
#执行change master to
mysql -e "$change;start slave"
#远程配置MHA配置文件
ssh 172.16.1.53 "\cp /service/mha/app11.cnf /service/mha/app1.cnf"
#远程启动MHA
ssh 172.16.1.53 "nohup masterha_manager --conf=/service/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /service/mha/manager.log 2>&1 &"
13.切换机制
1.读取是否有指定优先提升的主库设置
candidate_master=1
check_repl_delay=0
2.如果数据量不同
提升数据量多的主机为主库
3.如果数据量相同
按主机标签,值越小优先级越高
三、VIP漂移
1.VIP漂移的两种方式
1.通过keepalived的方式
2.通过MHA自带的脚本
2.配置MHA读取脚本
#编辑配置文件
[root@db03 ~]# vim /service/mha/app1.cnf
[server default]
master_ip_failover_script=/service/mha/master_ip_failover
3.编写脚本
[root@db03 ~]# cp ~/mha4mysql-manager-0.56/samples/scripts/master_ip_failover /service/mha/
或者上传现成的脚本
[root@db03 mha]# rz master_ip_failover
[root@db03 mha]# chmod 755 master_ip_failover
#编辑脚本
[root@db03 mha]# vim master_ip_failover
#在my变量下面添加以下内容
my $vip = '10.0.0.55/24';
my $key = '1';
my $ssh_start_vip = "/sbin/ifconfig eth1:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth1:$key down";
[root@db03 mha]# yum install -y dos2unix
[root@db03 mha]# dos2unix master_ip_failover
dos2unix: converting file master_ip_failover to Unix format ...
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SmjeBkA9-1588240909571)(C:\Users\12402\AppData\Roaming\Typora\typora-user-images\1588220018253.png)]
4.手动绑定VIP
#手动将网卡绑定在当前的主库上
[root@db01 ~]# ifconfig eth1:1 172.16.1.55/24
[root@db01 ~]# ip addr
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:f4:ca:65 brd ff:ff:ff:ff:ff:ff
inet 172.16.1.51/24 brd 172.16.1.255 scope global noprefixroute eth1
valid_lft forever preferred_lft forever
inet 172.16.1.55/24 brd 172.16.1.255 scope global secondary eth1:1
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fef4:ca65/64 scope link
valid_lft forever preferred_lft forever
#删除网卡上VIP
[root@db01 ~]# ifconfig eth1:1 down
5.启动MHA
[root@db03 ~]# nohup masterha_manager --conf=/service/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /service/mha/manager.lognager.log 2>&1 &
#正常启动前提:
1.语法必须正确
2.授权要正确
[root@db03 mha]# chmod 755 master_ip_failover
3.脚本格式要正确
[root@db03 mha]# dos2unix master_ip_failover
6.测试VIP漂移
#查看从库信息
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.16.1.51
Master_User: rep
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
#查看主库ip
[root@db01 ~]# ip a
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:f4:ca:65 brd ff:ff:ff:ff:ff:ff
inet 172.16.1.51/24 brd 172.16.1.255 scope global noprefixroute eth1
valid_lft forever preferred_lft forever
inet 172.16.1.55/24 brd 172.16.1.255 scope global secondary eth1:1
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fef4:ca65/64 scope link
valid_lft forever preferred_lft forever
#停止主库
[root@db01 ~]# systemctl stop mysql
#查看新主库IP
[root@db02 ~]# ip a
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:2b:e3:a1 brd ff:ff:ff:ff:ff:ff
inet 172.16.1.52/24 brd 172.16.1.255 scope global noprefixroute eth1
valid_lft forever preferred_lft forever
inet 172.16.1.55/24 brd 172.16.1.255 scope global secondary eth1:1
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe2b:e3a1/64 scope link
valid_lft forever preferred_lft forever