所有软件下载地址:链接:https://share.weiyun.com/QEgshNc8 密码:hg8mnz
MHA修复流程说明
(1) MHA通过masterha_manger脚本启动MHA的功能. (2) 在manager启动之前,会自动检查ssh互信(masterha_check_ssh)和主从状态(masterha_check_repl) (3) MHA-manager 通过 masterha_master_monitor脚本(每隔ping_interval秒) (4) masterha_master_monitor探测主库3次无心跳之后,就认为主库宕机了. (5) 进行选主过程 算法一: 读取配置文件中是否有强制选主的参数? candidate_master=1 #强制这台机器为主 check_repl_delay=0 #不管这台机器和主库相差多少数据,都忽略 算法二: 自动判断所有从库的日志量.将最接近主库数据的从库作为新主. 算法三: 按照配置文件先后顺序的进行选新主. (6) 数据补偿 判断主库SSH的连通性 情况一: SSH能连 调用 save_binary_logs脚本,立即保存缺失部分的binlog到各个从节点,恢复 情况二: SSH无法连接 调用 apply_diff_relay_logs 脚本,计算从库的relaylog的差异,恢复到2号从库 情况三:提供额外的binlog-server (7) 解除从库身份 (8) 剩余从库和新主库构建主从关系 (9) 应用透明 @@ (10) 故障节点自愈(待开发...)@@ (11) 故障提醒@ (12) 手动修复故障主库,并将故障主库身份转换成从库,修改MHA管理端配置文件,修改binlog server指向的地址
MHA搭建环境前提条件
1.最少三台MySQL服务器,1主2从。
2.MHA管理端不能放在MySQL主服务器上。
3.MHA为一次性环境,故障处理完毕后需要手动调整
4.在搭建MHA之前,三台数据库需要同时有MHA管理用户和mysql复制用户
5.MHA可以同时管理多个不同的mysql集群,启动MHA管理端时指定不同的配置文件即可
开始搭建
- 1.准备3三台mysql服务器,搭建好主从环境,所有节点都需要开启bin_log,额外准备一台MHA管理服务器,一共四台服务器
- 2.所有Mysql3台节点创建MHA需要用到的软连接,源节点根据软件安装情况更改,目标节点必须在/usr/bin下(就算mysql命令在环境变量中也需要链接到该目录下)
ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog ln -s /application/mysql/bin/mysql /usr/bin/mysql
- 3.所有主机进行免密认证
# ssh-keygen # ssh-copy-id #各节点验证,避免出现输入yes的情况
- 4.在mysql主库创建MHA用户(这个用户在三台mysql服务器上都需要创建,如果提前做好了主从,只需要在主库创建这个用户)
mysql> grant all privileges on *.* to mha@'%' identified by 'mha';
- 5.所有节点安装节点软件包(四个节点都装)
#安装依赖 yum install perl-DBD-MySQL -y #安装节点包 rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm
- 6.MHA管理节点安装管理软件(只有MHA管理节点安装)
#安装依赖 yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes #安装管理软件 rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm
- 7.创建MHA节点配置文件(只有MHA管理节点需要这个配置文件)
#创建配置文件目录 mkdir -p /etc/mha #创建日志目录,可以同时管理多个节点 mkdir -p /var/log/mha/app1 #编辑mha配置文件,针对app1集群的配置 cat > /etc/mha/app1.cnf <<EOF [server default] #日志文件名称,程序运行日志,排错都在这里面看 manager_log=/var/log/mha/app1/manager #工作目录 manager_workdir=/var/log/mha/app1 #mysql数据库存放binlog位置,mha会监控这个日志 master_binlog_dir=/var/lib/mysql #mha管理用户名 user=mha #mha管理用户密码 password=mha #心跳检测间隔时间 ping_interval=2 #mysql复制用户密码 repl_password=123 #MySQL复制用户名 repl_user=repl #ssh用户 ssh_user=root #高可用IP漂移脚本,下面会给出配置 master_ip_failover_script=/usr/local/bin/master_ip_failover #故障切换完成后发送邮件的脚本 report_script=/usr/local/bin/send #管理的mysql实例位置,故障选主时,从上至下顺序选主 [server1] hostname=192.168.2.3 port=3306 [server2] hostname=192.168.2.4 port=3306 [server3] hostname=192.168.2.5 port=3306 #数据补偿服务器,强制不能成为主库,二进制日志保存路径不能和mysql服务器二进制日志保存路径相同 [binlog1] no_master=1 hostname=192.168.2.5 master_binlog_dir=/data/mysql/binlog EOF
-
- 7.1主从切换脚本
这个脚本由perl语言编写,只需要对应更改下面内容,脚本文件放在MHA管理端配置文件master_ip_failover_script=/usr/local/bin/master_ip_failover对应位置,需要添加+x执行权限
my $vip = '192.168.3.88/24'; #高可用出来的VIP
my $key = '1'; #子网卡序号,例如eth0:1
my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip"; #开启vip,对应改网卡名
my $ssh_stop_vip = "/sbin/ifconfig ens33:$key down"; #关闭vip,对应改网卡名
[root@nginx ~]# cat /usr/local/bin/master_ip_failover #!/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 = '192.168.3.88/24'; my $key = '1'; my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip"; my $ssh_stop_vip = "/sbin/ifconfig ens33:$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 " IN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip=== "; if ( $command eq "stop" || $command eq "stopssh" ) { my $exit_code = 1; eval { print "Disabling the VIP on old master: $orig_master_host "; &stop_vip(); $exit_code = 0; }; if ($@) { warn "Got Error: $@ "; 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 "; &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 "; 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 "; }
-
- 7.2故障修复后发送邮件程序
三个文件如下,放在服务器上之后都需要有执行权限,脚本必须放在/usr/local/bin下
只需要修改testpl配置文件中的内容,MHA管理端只会调用send脚本,后续操作都有send脚本自行操作。(文件需要对应修改邮箱密码信息)
[root@nginx ~]# vim /usr/local/bin/testpl #!/bin/bash /usr/local/bin/sendEmail -o tls=no -f 发送邮件邮箱@126.com -t 接收邮件邮箱@qq.com -s smtp.126.com:25 -xu 发送邮箱的用户 -xp 发送邮箱的认证码 -u "MHA Waring" -m "YOUR MHA MAY BE FAILOVER" &>/tmp/sendmail.log
-
- 7.3数据补偿服务器
[binlog1] no_master=1 hostname=192.168.2.5 master_binlog_dir=/data/mysql/binlog
MHA管理端的这三条配置是binlog-server的配置,需要在对应服务器上创建该目录,并手动拉取数据。
MHA完成故障切换后,拉取二进制日志的主机需要重新配置mysql主库地址
#创建必要目录 mkdir -p /data/mysql/binlog chown -R mysql.mysql /data/* #手动拉取主库binlog日志 cd /data/mysql/binlog #必须进入到自己创建好的目录 mysqlbinlog -R --host=10.0.0.51 --user=mha --password=mha --raw --stop-never mysql-bin.000001 & #注意:拉取日志的起点 mysql-bin.000001,需要按照目前主库正在使用的binlog为起点.
- 8.MHA管理端进行状态检查(只有MHA管理端有这个命令)
#检查主机ssh状况 masterha_check_ssh --conf=/etc/mha/app1.cnf #出现下面状态代表ssh状态正常 #[info] All SSH connection tests passed successfully. #检查mysql复制状况 masterha_check_repl --conf=/etc/mha/app1.cnf #出现下面状态代表mysql复制状态正常 #MySQL Replication Health is OK.
- 9.第一次开启MHA前,需要手动在mysql主库服务器上添加VIP,后续漂移VIP是由MHA自动完成
/sbin/ifconfig ens33:1 192.168.2.88/24 up
- 10.检查顺利完成后,MHA节点开启管理端(MHA管理程序会以守护进程运行)
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover &> /var/log/mha/app1/manager.log & #--conf:指定配置文件 #--remove_dead_master_conf:mysql主库故障时,MHA自动从配置文件中移除坏掉的master #--ignore_last_failover:MHA切换主从后的8个小时内,如果mysql主库再次出现故障,MHA不会进行切换,加上ignore_last_failover,MHA不会管上一次切换是什么时候,只要mysql主库出现故障,就会切换
- 11.查看MHA状态
masterha_check_status --conf=/etc/mha/app1.cnf #出现如下状态代表正常 #app1 (pid:8050) is running(0:PING_OK), master:192.168.2.3
- 12.MHA日志
#MHA的工作日志,下面是个日志文件,不是目录 manager_log=/var/log/mha/app1/manager
- 13.其他命令
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信息
- 14.其他参数
candidate_master=1 #强制选主 check_repl_delay=0 #不管和主库相差多少数据,都忽略
模拟故障
- 停掉mysql主库
systemctl stop mysqld
- 查看MHA日志信息
1.原主库挂掉。
2.其中一台从库晋升为主库
3.另一台从库复制到新的主库上
4.成功发送邮件
----- Failover Report ----- app1: MySQL Master failover 192.168.3.156(192.168.3.156:3306) to 192.168.3.157(192.168.3.157:3306) succeeded Master 192.168.3.156(192.168.3.156:3306) is down! Check MHA Manager logs at nginx:/var/log/mha/app1/manager for details. Started automated(non-interactive) failover. Invalidated master IP address on 192.168.3.156(192.168.3.156:3306) The latest slave 192.168.3.157(192.168.3.157:3306) has all relay logs for recovery. Selected 192.168.3.157(192.168.3.157:3306) as a new master. 192.168.3.157(192.168.3.157:3306): OK: Applying all logs succeeded. 192.168.3.157(192.168.3.157:3306): OK: Activated master IP address. 192.168.3.161(192.168.3.161:3306): This host has the latest relay log events. Generating relay diff files from the latest slave succeeded. 192.168.3.161(192.168.3.161:3306): OK: Applying all logs succeeded. Slave started, replicating from 192.168.3.157(192.168.3.157:3306) 192.168.3.157(192.168.3.157:3306): Resetting slave info succeeded. Master failover to 192.168.3.157(192.168.3.157:3306) completed successfully. Tue May 12 13:26:13 2020 - [info] Sending mail..
- 查看VIP漂移情况:发现VIP顺利漂移到新的主库
- 查看binlog-server:发现复制二进制日志的守护进程已经自动结束
- 查看MHA管理端配置文件信息:发现原mysql主库配置已经被移除
故障修复
- 1.查看原主库上的VIP是否已经漂移到新主库上
- 2.更改原主库为从
- 查看MHA日志文件中,有一句是改主命令
[root@nginx ~]# grep CHANGE /var/log/mha/app1/manager Tue May 12 13:26:10 2020 - [info] All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='192.168.3.157', MASTER_PORT=3306, MASTER_LOG_FILE='mysql2-binlog.000006', MASTER_LOG_POS=154, MASTER_USER='repl', MASTER_PASSWORD='xxx'; Tue May 12 13:26:12 2020 - [info] Executed CHANGE MASTER.
-
- 启动原主库,在原主库上执行CHANGE MASTER TO命令到新的主库,复制账号的密码要对应修改
mysql> CHANGE MASTER TO MASTER_HOST='192.168.3.157', MASTER_PORT=3306, MASTER_LOG_FILE='mysql2-binlog.000006', MASTER_LOG_POS=154, MASTER_USER='repl', MASTER_PASSWORD='xxx'; mysql> START SLAVE;
- 3.恢复MHA管理端配置文件(将主库迁移时,自动删除的配置补上)
[server1] hostname=192.168.2.3 port=3306 [server2] hostname=192.168.2.4 port=3306 [server3] hostname=192.168.2.5 port=3306
- 4.清理binlog-server上原有的二进制日志,并重新复制新的主库二进制日志。二进制日志名称可以在新主库上执行SHOW MASTER STATUS查看
cd /data/mysql/binlog rm -rf /data/mysql/binlog/* mysqlbinlog -R --host=192.168.2.4 --user=mha --password=mha --raw --stop-never mysql-bin.000001 &
- 5.重新启动MHA管理端,并查看服务状态
[root@nginx ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover &>> /var/log/mha/app1/manager.log & [root@nginx ~]# masterha_check_status --conf /etc/mha/app1.cnf app1 (pid:19214) is running(0:PING_OK), master:192.168.2.4
Atlas读写分离
- 安装atlas软件包
rpm -ivh Atlas-2.2.1.el6.x86_64.rpm
- 修改配置文件,默认配置文件在/usr/local/mysql-proxy/conf下,配置文件中有详细的中文注释。
[mysql-proxy] #管理接口的用户名 admin-username = user #管理接口的密码 admin-password = pwd #Atlas后端连接的MySQL主库的IP和端口,可设置多项,用逗号分隔 proxy-backend-addresses = 10.0.0.55:3306 #Atlas后端连接的MySQL从库的IP和端口,@后面的数字代表权重,用来作负载均衡,若省略则默认为1,可设置多项,用逗号分隔 proxy-read-only-backend-addresses = 10.0.0.51:3306@1,10.0.0.53:3306@2 #用户名与其对应的加密过的MySQL密码,密码使用PREFIX/bin目录下的加密程序encrypt加密,下行的user1和user2为示例,将其替换为你的MySQL的用户名和加密密码! pwds = repl:3yb5jEku5h4=,mha:O2jBXONX098= #设置Atlas的运行方式,设为true时为守护进程方式,设为false时为前台方式,一般开发调试时设为false,线上运行时设为true,true后面不能有空格。 daemon = true #设置Atlas的运行方式,设为true时Atlas会启动两个进程,一个为monitor,一个为worker,monitor在worker意外退出后会自动将其重启,设为false时只有worker,没有monitor,一般开发调试时设为false,线上运行时设为true,true后面不能有空格。 keepalive = true #工作线程数,对Atlas的性能有很大影响,可根据情况适当设置 event-threads = 8 #日志级别,分为message、warning、critical、error、debug五个级别 log-level = message #日志存放的路径 log-path = /usr/local/mysql-proxy/log #SQL日志的开关,可设置为OFF、ON、REALTIME,OFF代表不记录SQL日志,ON代表记录SQL日志,REALTIME代表记录SQL日志且实时写入磁盘,默认为OFF sql-log=ON #应用程序访问的端口 proxy-address = 0.0.0.0:33060 #管理员访问的端口 admin-address = 0.0.0.0:2345 #默认字符集,设置该项后客户端不再需要执行SET NAMES语句 charset=utf8 #允许连接Atlas的客户端的IP,可以是精确IP,也可以是IP段,以逗号分隔,若不设置该项则允许所有IP连接,否则只允许列表中的IP连接 #client-ips = 127.0.0.1, 192.168.1
- 启动atlas,启动命令中的test是根据配置文件名称来的。atlas可以有多个实例,根据配置文件来区别启动
[root@nginx mysql-proxy]# /usr/local/mysql-proxy/bin/mysql-proxyd test start OK: MySQL-Proxy of test is started
- 测试atlas读写分离功能,这里连接的就是atlas的代理端口
mysql -umha -pmha -h 10.0.0.53 -P 33060 #测试读操作:会发现语句会负载均衡到两台从库上 mysql> SELECT @@server_id; +-------------+ | @@server_id | +-------------+ | 1 | +-------------+ 1 row in set (0.02 sec) mysql> SELECT @@server_id; +-------------+ | @@server_id | +-------------+ | 3 | +-------------+ 1 row in set (0.01 sec) #测试写操作:会发现写操作在主库上 mysql> begin;select @@server_id;commit; Query OK, 0 rows affected (0.01 sec) +-------------+ | @@server_id | +-------------+ | 2 | +-------------+
Atlas管理端口应用
- 连接atlas管理端
#用户名、密码和端口都在atlas配置文件中 mysql -uuser -ppwd -h 192.168.1.92 -P 2345
- 打印帮助信息
MySQL [(none)]> SELECT * FROM HELP;
- 查看所有后端节点
MySQL [(none)]> SELECT * FROM backends; +-------------+--------------------+-------+------+ | backend_ndx | address | state | type | +-------------+--------------------+-------+------+ | 1 | 192.168.3.88:3306 | up | rw | | 2 | 192.168.3.156:3306 | up | ro | | 3 | 192.168.3.161:3306 | up | ro | +-------------+--------------------+-------+------+ 3 rows in set (0.00 sec)
- 下线一个节点(不是删除),请求就不会到这个后端
MySQL [(none)]> SET OFFLINE 2; +-------------+--------------------+---------+------+ | backend_ndx | address | state | type | +-------------+--------------------+---------+------+ | 2 | 192.168.3.156:3306 | offline | ro | +-------------+--------------------+---------+------+ 1 row in set (0.00 sec)
- 上线一个节点
MySQL [(none)]> SET ONLINE 2; +-------------+--------------------+---------+------+ | backend_ndx | address | state | type | +-------------+--------------------+---------+------+ | 2 | 192.168.3.156:3306 | unknown | ro | +-------------+--------------------+---------+------+ 1 row in set (0.00 sec)
- 添加一个slave节点(读节点)
> add slave 127.0.0.1:3306
- 删除一个节点
> remove backend 1; 或 > remove client 192.168.1.2
- 查询后端用户名密码
MySQL [(none)]> SELECT * FROM pwds; +----------+--------------+ | username | password | +----------+--------------+ | repl | /iZxz+0GRoA= | | mha | /iZxz+0GRoA= | +----------+--------------+ 2 rows in set (0.00 sec)
- 添加后端mysql服务器用户,注意!在mysql服务器中仍要手动创建对应用户
MySQL [(none)]> ADD PWD lee:123456; Empty set (0.00 sec)
- 保存配置到配置文件中,所有命令都是在内存中更改,使用一下命令会保存到配置文件中
MySQL [(none)]> SAVE CONFIG; Empty set (0.00 sec)