MHA(Master High Availability)是一款开源的mysql高可用程序,目前在mysql高可用方面是一个相对成熟的解决方案。MHA 搭建的前提是MySQL集群中已经搭建了MySql Replication环境,有了Master/Slave节点。MHA的主要做用就是监测到Master节点故障时会提高主从复制环境中拥有最新数据的Slave节点成为新的master节点。同时,在切换master期间,MHA会经过从其余的Slave节点来获取额外的信息来避免一致性的问题,整个的切换过程对于应用程序而言是彻底透明的。MHA还提供了master节点在线切换功能,即按需切换master/slave节点。 node
MHA 服务有两个角色,MHA Manager 和 MHA Node
MHA Manager: 一般单独部署在一台独立机器上管理 master/slave 集群,每一个master/slave 集群能够理解为一个application。mysql
MHA Node: 运行在每台mysql 服务器(master/slave)上。它经过监控具有解析和清理logs功能来加快故障转移。git
总体上的架构以下图所示。 github
MHA 在自动切换的过程当中会从宕掉的MySql master节点中保存二进制日志,以保证数据的完整性。可是若是master节点直接宕机了呢,或者网络直接不能联通了呢?MHA就没有办法获取master的二进制日志,也就没有办法保证数据的完整性了。这也就是为何MHA应该与MySql主从复制结合起来。这样的话,只要有一个slave节点从master节点复制到了最新的日志,MHA就能够将最近的二进制日志应用到其余的slave节点上,这样就能够最大限度上保证数据的完整性。 sql
MHA 自动切换的原理能够总结为下面几点.shell
MHA 提供了不少的程序组件,经过这些组件,咱们 能够很方便的管理MHA集群。 后端
Manager节点:centos
Node节点:服务器
在实际的生产环境中有不少的因素须要考虑,例如MHA Manager的单点问题。可是咱们因为环境有限,因此就暂时不考虑这些。这次实验中实验环境以下。网络
担任角色 | 主机名 | 地址 | 功能描述 | 对应软件版本 |
---|---|---|---|---|
MHA Manager | manager | 192.168.0.20 | MHA Manager,控制Master节点故障转移 | mha4mysql-manager-0.56-0.el6.noarch |
MySql Master | master | 192.168.0.21 | MySql Master 节点 | Mariadb-server-5.5.56-2.el7 |
MySql Slave | Slave1 | 192.168.0.22 | Mysql Repliaction集群中的Slave1 节点 | Mariadb-server-5.5.56-2.el7 |
MySql Slave | Slave2 | 192.168.0.26 | MySql Repliaction 集群中的Slave2节点 | Mariadb-server-5.5.56-2.el7 |
某种意义上说,Master节点不会一直充当master节点。Master节点从故障状态中恢复以后,颇有可能充当的是slave节点,因此咱们在安装插件的时候,不作区别对待。
mysql 支持多种插件/var/lib/mysql/plugin 目录下,须要安装方可以使用。在Master(192.168.0.21),和Slave(192.168.0.22,192.168.0.26)节点上安装semisync_master.so
semisync_slave.so
两个插件。
MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
而后在三台主机上开启下面两个参数
MariaDB [(none)]> SET GLOBAL rpl_semi_sync_master_enabled=ON; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> SET GLOBAL rpl_semi_sync_slave_enabled=ON; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE 'rpl_semi%'; +------------------------------------+-------+ | Variable_name | Value | +------------------------------------+-------+ | rpl_semi_sync_master_enabled | ON | | rpl_semi_sync_master_timeout | 10000 | | rpl_semi_sync_master_trace_level | 32 | | rpl_semi_sync_master_wait_no_slave | ON | | rpl_semi_sync_slave_enabled | ON | | rpl_semi_sync_slave_trace_level | 32 | +------------------------------------+-------+ 6 rows in set (0.00 sec)
到目前而言,三台主机之间没有差异,也没有角色上的区分。接下来咱们开始设置master与slave来实现主从复制。
编辑 /etc/my.cnf.d/server.cnf 文件,加入下面这样一段配置
[mariadb] server-id=1 #Master设置1,Slave1设置2,Slave2设置3 log-bin=mysql-bin relay-log=mysql-relay-bin relay_log_purge=0
修改完配置文件以后,重启Mariadb. systemctl restart mariadb
在master节点上进行操做
# 这里须要记住 File 以及Position的数据,在SLAVE 节点上要用到 MariaDB [(none)]> show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000001 | 245 | | | +------------------+----------+--------------+------------------+ 1 row in set (0.00 sec) MariaDB [(none)]> GRANT REPLICATION MASTER ON *.* TO 'repl'@'%' IDENTIFIED BY '123'; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.00 sec)
在slave节点上进行操做
MariaDB [(none)]> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%' IDENTIFIED BY '123'; Query OK, 0 rows affected (0.01 sec) MariaDB [(none)]> CHANGE MASTER TO -> MASTER_HOST='192.168.0.21', -> MASTER_PORT=3306, -> MASTER_USER='repl', -> MASTER_PASSWORD='123', -> MASTER_LOG_FILE='mysql-bin.000001', -> MASTER_LOG_POS=245; Query OK, 0 rows affected (0.03 sec) MariaDB [(none)]> start slave; Query OK, 0 rows affected (0.00 sec)
上面的操做完成后,在master主机上查看master的状态。
MariaDB [(none)]> SHOW SLAVE HOSTS; +-----------+------+------+-----------+ | Server_id | Host | Port | Master_id | +-----------+------+------+-----------+ | 3 | | 3306 | 1 | | 2 | | 3306 | 1 | +-----------+------+------+-----------+
在slave主机上能够查看slave主机的状态。
*************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.0.21 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 245 ............. ............. Slave_IO_Running: Yes Save_SQL_Running: Yes .............
在Master节点上建立MHA监控所须要的用户,该用户会同步到slave端。
MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO 'mha_rep'@'%' IDENTIFIED BY '123'; MariaDB [(none)]> flush privileges;
至此,MySql 主从复制环境就搭建好了。下面就能够开始来安装MHA了。
注:在查看slave节点状态时,若是出现问题,能够检查一下SELinux,iptables,以及其余权限问题,在实验开始以前,最好先将这些环境设置好,避免出现问题。
MHA 集群中的各节点之间须要基于SSH互相通讯,以实现远程控制以及数据管理功能。简单起见,咱们以Manager节点为例,而后将生成的文件发送到须要管理的主机上。四个节点都须要进行这个操做。
[root@manager ~]# ssh-keygen -t rsa [root@manager ~]# for i in 21 22 26;do ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.0.$i; done
这样MHA Manager就实现了经过SSH免密管理其余的mysql节点
MHA 官方提供了rpm的安装包,经过搜索能够找到。CentOS 7 能够直接使用el6 的rpm安装包。下面是本次实验中rpm安装包的下载地址。https://github.com/yoshinorim/mha4mysql-manager/wiki/Downloads。
在全部节点上安装node安装包
[root@manager ~]# yum install mha4mysql-node-0.56-0.el6.noarch.rpm
在Manager节点上安装manager安装包
[root@manager ~]# yum install mha4mysql-manager-0.56-0.el6.noarch.rpm
还能够在上述网站上下载源码包,里面有不少的例子和脚本能够直接拿来使用。 将下载的源码包解压以后在samples/scripts下的全部脚本复制到/usr/bin目录(由于安装的mha manager的相关命令就在/usr/bin/目录下,可使用rpm -ql mha4mysql-manager-0.56-0.el6 来查看)下。
脚本以下:
master_ip_failover #自动切换时vip管理的脚本,不是必须,若是咱们使用keepalived的,咱们能够本身编写脚本完成对vip的管理,好比监控mysql,若是mysql异常,咱们中止keepalived就行,这样vip就会自动漂移 master_ip_online_change #在线切换时vip的管理,不是必须,一样能够能够自行编写简单的shell完成 power_manager #故障发生后关闭主机的脚本,不是必须 send_report #因故障切换后发送报警的脚本,不是必须,可自行编写简单的shell完成。
这里有一点须要注意,拷贝到/usr/bin 目录下的文件若是没有执行权限,要加上执行权限。
Manager节点须要为每一个监控的master/slave 集群提供专用的配置文件,而全部的master/slave集群也能够共享全局配置。全局配置文件默认在/etc/masterha_default.cnf,其为可选配置。若是仅监控一组master/slave集群,也能够直接经过application 的配置来提供给个服务器的默认配置信息。而灭个application的配置文件路径为自定义,咱们的实例中,只有一个master/slave集群,因此咱们就定义一个配置文件好了。
[root@manager ~]# cat /etc/masterha/app1.cnf [server default] manager_workdir=/etc/masterha manager_log=/etc/masterha/manager.log user=mha_rep password=123 ping_interval=3 remote_workdir=/etc/masterha repl_user=repl repl_password=123 ssh_user=root master_ip_failover_script=/usr/bin/master_ip_failover master_ip_online_change_script=/usr/bin/master_ip_online_change report_script=/usr/bin/send_report shutdown_script="" secondary_check_script=/usr/bin/masterha_secondary_check -s 192.168.0.22 -s 192.168.0.26 --user=root --master_host=192.168.0.21 --master_ip=192.168.0.21 --master_port=3306 [server1] hostname=192.168.0.21 port=3306 master_binlog_dir=/var/lib/mysql/ candidate_master=1 check_repl_delay=0 [server2] hostname=192.168.0.22 port=3306 master_binlog_dir=/var/lib/mysql/ candidate_master=1 check_repl_delay=0 [server3] hostname=192.168.0.26 port=3306 master_binlog_dir=/var/lib/mysql/ no_master=1
编辑一下 /etc/masterha_default.cnf 文件,添加一些全局的配置。配置文件的内容以下。
[root@manager ~]# cat /etc/masterha_default.cnf [server default] user=mha_rep password=123 repl_user=repl repl_password=123 ssh_user=root ping_interval=3 master_binlog_dir=/var/lib/mysql remote_workdir=/etc/masterha secondary_check_script=/usr/bin/masterha_secondary_check -s 192.168.0.22 -s 192.168.0.26 --user=root --master_host=192.168.0.21 --master_ip=192.168.0.21 --master_port=3306 # 设置自动failover时候的切换脚本; master_ip_failover_script=/usr/bin/master_ip_failover # 设置手动切换时候的切换脚本; master_ip_online_change_script=/usr/bin/master_ip_online_change # 设置发生切换后发送的报警的脚本; report_script=/usr/bin/send_report # 设置故障发生后关闭故障主机脚本(该脚本的主要做用是关闭主机防止发生脑裂,这里没有使用); shutdown_script=""
在master,slave1 和slave2 节点上执行下面的命令检查一下mysqlbinlog和mysql 命令的位置。
[root@master ~]# type mysqlbinlog mysqlbinlog is /usr/bin/mysqlbinlog [root@master ~]# type mysql mysql is /usr/bin/mysql
必定要确保 mysqlbinlog 和mysql 两个命令在 /usr/bin 目录下。因为我安装的是mariadb ,因此这两个文件默认就在这两个目录,若是是其余版本的mysql,不在这两个目录下的话可使用软链接的方式,在这个目录下添加两个软链接。
不然,在进行检查的时候,会出现以下的相似错误。
mysqlbinlog
..... Can't exec "mysqlbinlog": No suchfile or directory at /usr/local/share/perl5/MHA/BinlogManager.pm line 106. mysqlbinlog version command failed with rc1:0, please verify PATH, LD_LIBRARY_PATH, and client options .....
mysql
..... Testing mysql connection and privileges..sh: mysql: command not found mysql command failed with rc 127:0! .....
在master 节点上进行操做,给ens33网卡添加一个VIP,这样用户访问的时候,就会能够经过VIP进行访问,并不须要关心MySQL集群中的具体细节。同时若是master宕机以后,VIP会自动进行转移,并不会影响到用户的访问,后端VIP漂移的过程对用户来讲彻底透明。
[root@manager ~]# ifconfig ens33:1 192.168.0.88
在MHA manager上进行操做,修改/usr/bin/master_ip_failover脚本以下,主要是VIP的修改。
[root@centos7-1 ~]# cat /usr/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.0.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 "\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"; # 这一行很重要,表示在master上mysql服务中止以后,关闭掉VIP,以避免地址冲突 &stop_vip(); &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"; }
通过上述的一系列的的配置和操做,咱们就顺利的配置好了MySql replication 环境和MHA 环境,接下来开始验证一下。
在MHA manager 上进行一下下面的操做。
# 检测主机之间的SSH 联通性 [root@manager ~]# masterha_check_ssh --conf=/etc/masterha/app1.cnf ..... # 省略了不少非关键信息 出现相似下面的 successfully 表示SSH 联通性检测成功 Sun Jan 14 20:09:30 2018 - [info] All SSH connection tests passed successfully.
# 检测mysql 复制集群的配置参数是否正确 [root@manager ~]# masterha_check_ssh --conf=/etc/masterha/app1.cnf ....... # 能够看到咱们配置的master/slave信息 192.168.0.21(192.168.0.21:3306) (current master) +--192.168.0.22(192.168.0.22:3306) +--192.168.0.26(192.168.0.26:3306) ..... # 省略了不少非必要信息,出现下面的Health is OK ,说明主从复制检测成功 MySQL Replication Health is OK.
在manager 节点上进行操做。
[root@manager ~]# nohup masterha_manager --conf=/etc/masterha/app1.cnf < /dev/null > /etc/masterha/manager.log 2>&1 & [1] 7861 [root@manager ~]# masterha_check_status --conf=/etc/masterha/app1.cnf app1 (pid:7861) is running(0:PING_OK), master:192.168.0.21
若是想要中止MHA 能够执行以下的命令
[root@manager ~]# masterha_stop --conf=/etc/masterha/app1.cnf Stopped app1 successfully. [1]+ Exit 1 nohup masterha_manager --conf=/etc/masterha/app1.cnf < /dev/null > /etc/masterha/manager.log 2>&1
systemctl stop mariadb
在manager节点查看 manager.log 的日志,能够看到下面的切换过程
----- Failover Report ----- app1: MySQL Master failover 192.168.0.21(192.168.0.21:3306) to 192.168.0.22(192.168.0.22:3306) succeeded Master 192.168.0.21(192.168.0.21:3306) is down! Check MHA Manager logs at manager:/etc/masterha/manager.log for details. Started automated(non-interactive) failover. Invalidated master IP address on 192.168.0.21(192.168.0.21:3306) The latest slave 192.168.0.22(192.168.0.22:3306) has all relay logs for recovery. Selected 192.168.0.22(192.168.0.22:3306) as a new master. 192.168.0.22(192.168.0.22:3306): OK: Applying all logs succeeded. 192.168.0.22(192.168.0.22:3306): OK: Activated master IP address. 192.168.0.26(192.168.0.26:3306): This host has the latest relay log events. Generating relay diff files from the latest slave succeeded. 192.168.0.26(192.168.0.26:3306): OK: Applying all logs succeeded. Slave started, replicating from 192.168.0.22(192.168.0.22:3306) 192.168.0.22(192.168.0.22:3306): Resetting slave info succeeded. Master failover to 192.168.0.22(192.168.0.22:3306) completed successfully.
注意,故障转移完成以后,manager会自动中止,此时使用masterha_check_status命令检测将会是下面这种结果.
[root@manager ~]# masterha_check_status --conf=/etc/masterha/app1.cnf app1 is stopped(2:NOT_RUNNING).
在新的master主机slave1上进行查看,master_id 已经进行了切换,而且少了一台slave 主机。
MariaDB [(none)]> show slave hosts; +-----------+------+------+-----------+ | Server_id | Host | Port | Master_id | +-----------+------+------+-----------+ | 3 | | 3306 | 2 | +-----------+------+------+-----------+ 1 row in set (0.00 sec)
在slave2主机上查看slave 的当前状态 。
MariaDB [(none)]> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.0.22 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000004 Read_Master_Log_Pos: 384 Relay_Log_File: mysql-relay-bin.000002 Relay_Log_Pos: 529 Relay_Master_Log_File: mysql-bin.000004 Slave_IO_Running: Yes Slave_SQL_Running: Yes .......................
能够看到最新的master的IP 已经变成了以前slave1 主机的IP地址,这说明master 切换成功。
在新的master 主机上查看ip地址的变化,若是VIP 漂移成功说明,以前的配置没有问题。
[root@slave1 ~]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:50:56:37:c4:5e brd ff:ff:ff:ff:ff:ff inet 192.168.0.88/24 brd 192.168.0.255 scope global ens33:1 valid_lft forever preferred_lft forever inet 192.168.0.22/24 brd 192.168.0.255 scope global secondary dynamic ens33 valid_lft 6390sec preferred_lft 6390sec inet6 fe80::e9cb:24a6:f81d:1810/64 scope link valid_lft forever preferred_lft forever
在旧的master主机上查看VIP是否已经被移除。
[root@master ~]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:50:56:29:d0:2d brd ff:ff:ff:ff:ff:ff inet 192.168.0.21/24 brd 192.168.0.255 scope global dynamic ens33 valid_lft 7198sec preferred_lft 7198sec inet6 fe80::c28a:e648:5959:5ad6/64 scope link valid_lft forever preferred_lft forever
若是上面两项的检测都没有问题,说明在实际的使用过程当中VIP 就不会产生地址冲突了。 并且地址切换过程对用户来讲,基本上没有任何感知,这样就保证了mysql服务的高可用了。
生产中mysql服务停掉能够当即监监控到,并且这基本上属于以及故障须要当即进行排除。
从新恢复宕掉的mysql服务比较好的思路是,将其基于最新的master节点的数据备份进行数据恢复,而后从新启动服务,将其设置为slave节点,并加入到新的master集群,以后重启MHA监控。
备份还原过程,此处再也不赘述。将启动后的节点从新加入到新的master集群中。过程与以前介绍的相似。
MariaDB [(none)]> CHANGE MASTER TO -> MASTER_HOST='192.168.0.22', -> MASTER_PORT=3306, -> MASTER_USER='repl', -> MASTER_PASSWORD='123', -> MASTER_LOG_FILE='mysql-bin.000004', -> MASTER_LOG_POS=384; Query OK, 0 rows affected (0.01 sec) MariaDB [(none)]> start slave; Query OK, 0 rows affected (0.00 sec)
在新的master节点上查看最新的slave主机状态。
MariaDB [(none)]> show slave hosts; +-----------+------+------+-----------+ | Server_id | Host | Port | Master_id | +-----------+------+------+-----------+ | 1 | | 3306 | 2 | | 3 | | 3306 | 2 | +-----------+------+------+-----------+ 2 rows in set (0.00 sec)
能够看到slave 主机的server_id 已经变化了。
在manager上修改/etc/masterha/app1.cnf中secondary_check_script中的master IP值,将新的master ip修改上
secondary_check_script=/usr/bin/masterha_secondary_check -s 192.168.0.21 -s 192.168.0.26 --user=root --master_host=192.168.0.22 --master_ip=192.168.0.22 --master_port=3306
修改/etc/masterha_default.cnf 中secondary_check_script 中的IP地址
secondary_check_script=/usr/bin/masterha_secondary_check -s 192.168.0.21 -s 192.168.0.26 --user=root --master_host=192.168.0.22 --master_ip=192.168.0.22 --master_port=3306
在Manager 上启动MHA 而后检查MHA的状态
[root@centos7-1 ~]# masterha_check_repl --conf=/etc/masterha/app1.cnf ......... 192.168.0.22(192.168.0.22:3306) (current master) +--192.168.0.21(192.168.0.21:3306) +--192.168.0.26(192.168.0.26:3306) ...... MySQL Replication Health is OK.
启动MHA ,检查MHA的状态
[root@manager ~]# nohup masterha_manager --conf=/etc/masterha/app1.cnf < /dev/null > /etc/masterha/manager.log 2>&1 & [1] 9186 [root@manager ~]# masterha_check_status --conf=/etc/masterha/app1.cnf app1 (pid:9186) is running(0:PING_OK), master:192.168.0.22
至此,MySql MHA 的配置与测试基本就完成了。在实际生产中,至少也应该对MySQL主从复制进行一下验证,而且对MySQL 故障进行了解,以便在实际生产中可以有效的排除故障。