1  概述

当主服务器挂掉的时候,考虑将从服务器提升为主服务器,一般是将数据落后最少的从服务器提升为主服务器,但是,这里有个问题是,如果被提升的从服务器上可能有些没完成的事务在其他从服务器上已经完成,因此,被提升的从服务器还是存在数据不同步的情况,要解决的方法是借助外在的辅助机制,监控所有从服务器的事务完成情况,并将所有进度做并集,将每一个节点完成的事务并集补全在其中一台数据最接近于主服务的从服务器上,因此补上并集的从服务器数据是最完整的。此时,主服务器异常时,就将该从服务器提升为主服务器。

外部的辅助工具,最常用的是MHA,主节点高可用的缩写,是一外部辅助工具,不仅监控备用解决的事务情况,而且辅助将从服务器提升成为新的主服务器,而且不造成数据的不同步。

MHA(Master HA)是一款开源的 MySQL 的高可用程序,它为 MySQL 主从复制架构提供了 automating master failover 功能。MHA 在监控到 master 节点故障时,会提升其中拥有最新数据的 slave 节点成为新的 master 节点,在此期间,MHA 会通过于其它从节点获取额外信息来避免一致性方面的问题。MHA 还提供了 master 节点的在线切换功能,即按需切换

master/slave 节点。

MHA 服务有两种角色,MHA Manager(管理节点)和 MHA Node(数据节点)

MHA Manager:通常单独部署在一台独立机器上管理多个 master/slave 集群(可以直接配置在调度器上),每个master/slave 集群称作一个 application;

MHA node:运行在每台 MySQL 服务器上(master/slave/manager),它通过监控具备解析和清理 logs 功能的脚本来加快故障转移。

架构图如下:

2 Architecture of MHA

MySQL 复制集群中的 master 故障时,MHA 按如下步骤进行故障转移。

特殊情况下,如果所有的从节点都缺失某一事务,那么就将该事务回退。

 

3  MHA 组件

MHA 会提供诸多工具程序,其常见的如下所示。

Manager 节点:

- masterha_check_ssh:MHA 依赖的 SSH 环境检测工具,任何主机间两两都要实现无密钥的连接,这里有个省事的方法是将同一对密钥对复制到其他节点上;

- masterha_check_repl:MySQL 复制环境检测工具;

- masterha_manager:MHA 服务主程序;

- masterha_check_status:MHA 运行状态探测工具;

- masterha_master_monitor:MySQL master 节点可用性监测工具;

- masterha_master_switch:master 节点切换工具;

- masterha_conf_host:添加或删除配置的节点;

- masterha_stop:关闭 MHA 服务的工具;

Node 节点:

- save_binary_logs:保存和复制 master 的二进制日志:

- apply_diff_relay_logs:识别差异的中继日志事件并应用于其它 slave:

- filter_mysqlbinlog:去除不必要的 ROLLBACK 事件(MHA 已不再使用这个工具):

- purge_relay_logs:清除中继日志(不会阻塞 SQL 线程):

自定义扩展:

- secondary_check_script:通过多条网络路由检测 master 的可用性;

- master_ip_failover_script:更新 application 使用的 masterip;

- shutdown_script:强制关闭 master 节点;

- report_script:发送报告,发生故障时发生邮件等通知;

- init_conf_load_script:加载初始配置参数;

- master_ip_online_change_script:更新 master 节点 ip 地址;

4  准备 MySQL Replication 环境

MHA 对 MySQL 复制环境有特殊要求,例如各节点都要开启二进制日志及中继日志,各从节点必须显式启用其 read-only 属性,并关闭 relay_log_purge 功能等,这里先对其配置做事先说明。

本实验环境共有四个节点,其角色分配如下所示。

node75: MHA Manager

node71: MariaDB master

node76: MariaDB slave

node77: MariaDB slave

如果本地dns可以解析各节点,或者在各节点的/etc/hosts 文件配置内容中添加:

192.168.1.75 node75.ghbsunny.cn node75

192.168.1.71 node71.ghbsunny.cn node71

192.168.1.76 node76.ghbsunny.cn node76

192.168.1.77 node77.ghbsunny.cn node77

初始主节点 master 配置:

[root@node71 ~]#vim /etc/my.cnf.d/server.cnf 

[server]

skip_name_resolve = ON

innodb_file_per_table = ON

max_connections = 20000

log_bin = master-log

relay-log=relay-bin #因为主节点可能会成为从节点,所以要启用中继日志

server_id = 1 

所有 slave 节点(76和77)依赖的配置:

[root@node76 ~]#vim /etc/my.cnf.d/server.cnf 

[server]

skip_name_resolve = ON

innodb_file_per_table = ON

max_connections = 20000

server_id=2 # 复制集群中的各节点的 id 均必须惟一,另一个节点为3;

relay-log=relay-bin 

log-bin=master-bin 

relay_log_purge=0 #关闭中继日志自动修剪功能,因为中继日志默认会自动修剪 

read_only=1 #从节点要设置为只读,防止出现数据和主节点不一致

重启三台mysql服务器

在主节点上查看当前二进制文件是哪个,以及位置在哪里,待会复制需要从哪个二进制文件的哪个位置进行复制

在71上执行如下命令

MariaDB [(none)]> show master status\G;

在服务器主节点71上授权两个账号用来授权mha管理和从节点复制的权限

按上述要求分别配置好主从节点之后,按 MySQL 复制配置架构的配置方式将其配置完成, 并启动 master 节点和各 slave 节点,以及为各 slave 节点启动其 IO 和 SQL 线程,确保主从复制运行无误。

而后,在所有MySQL 节点授权拥有管理权限的用户可在本地网络中有其它节点上远程访问。当然,此时仅需要且只能在 master 节点运行类似如下 SQL 语句即可。如授权mhadmin账号,使得该账号可以对mysql服务器具有管理权限

MariaDB [(none)]> GRANT ALL ON *.* TO 'mhaadmin'@'192.168.1.%' IDENTIFIED BY 'Pass123456';

MariaDB [(none)]> flush privileges;

另外,授权账号sunnycopy具有复制的权限即可,使得从服务器可以往主服务器复制二进制文件到中继文件中

MariaDB [(none)]> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'sunnycp'@'192.168.1.%' IDENTIFIED BY 'Pass123456';

MariaDB [(none)]> flush privileges;

授权完成后,在两个从节点76和77上上启用复制进程

MariaDB [(none)]> change master to master_host='192.168.1.71',master_user='sunnycp',master_password='Pass1234',master_log_file='master-log.000010',master_log_pos=466;

MariaDB [(none)]> start slave;

查看复制是否完成

MariaDB [(none)]> show slave status\G;

查看授权的两个账号是否已经复制过来

MariaDB [(none)]> select host,user from mysql.user;

4  安装配置 MHA

4.1 准备基于 ssh 互信通信环境

MHA 集群中的各节点彼此之间均需要基于 ssh 互信通信,以实现远程控制及数据管理功能。简单起见,可在 Manager 节点生成密钥对儿,并设置其可远程连接本地主机后,将私钥文件及 authorized_keys 文件复制给余下的所有节点即可。

下面的操作在 manager 节点操作即可。

~]# ssh-keygen -t rsa -P ''

~]# cat .ssh/id_rsa.pub >> .ssh/authorized_keys

~]# chmod go= .ssh/authorized_keys

~]# scp -p .ssh/id_rsa .ssh/authorized_keys   root@node71:/root/.ssh/

~]# scp -p .ssh/id_rsa .ssh/authorized_keys   root@node76:/root/.ssh/

~]# scp -p .ssh/id_rsa .ssh/authorized_keys   root@node77:/root/.ssh/

以上步骤可以直接用for循环实现,假设有七台机器

在192.168.1.71上执行

[root@CentOS7A .ssh]#ssh-keygen -t rsa -P ''

生成密钥对,将密钥对发送给其他机器

[root@CentOS7A .ssh]#cat .ssh/id_rsa.pub >> .ssh/authorized_keys

[root@CentOS7A .ssh]#chmod go= .ssh/authorized_keys

[root@CentOS7A .ssh]#for i in 71 72 73 75 76 77 78;do scp -p /root/.ssh/id_rsa /root/.ssh/authorized_keys [email protected].$i:/root/.ssh/ ;done

注意:请事先确保 所有机器上的/root/.ssh 目录存在,且在/root/.ssh 目录下不能有id_rsa.pub,否则有id_rsa.pub的主机连接其他机器还是需要输入密码。或者,可以直接把71上的id_rsa.pub也都拷贝到其他机器上就不存在这个问题了。

4.2 安装 MHA

除 了 源 码 包 , MHA 官 方 也 提 供 了 rpm 格 式 的 程 序 包 , 其 下 载 地 址 为https://code.google.com/p/mysql-master-ha/wiki/Downloads?tm=2。CentOS 7 系统可直接使用适用于 el6 的程序包。另外,MHA Manage 和 MHA Node 程序包的版本并不强制要求一致。

这里采用提前下载好的服务包

Manager 节点:注意,如果 mha4mysql-manager安装不成功,建议先安装mha4mysql-node后安装mha4mysql-manager,因为存在依赖关系。另外,server端也没有启动脚本,需要手动启动

~]# yum install mha4mysql-manager-0.56-0.el6.noarch.rpm

所有节点,包括 Manager:

~]# yum install mha4mysql-node-0.56-0.el6.noarch.rpm

4.3 初始化 MHA

Manger 节点需要为每个监控的 master/slave 集群提供一个专用的配置文件, 而所有的

master/slave 集群也可共享全局配置。全局配置文件默认为/etc/masterha_default.cnf,其为可选配置。如果仅监控一组 master/slave 集群,也可直接通过 application 的配置来提供各服务器的默认配置信息。而每个 application 的配置文件路径为自定义,例如,本示例中将使用

/etc/masterha/app1.cnf,其内容如下所示。

在75节点上

首先创建相关目录首先创建相关目录

[root@node75 mha]#mkdir  /etc/masterha

[root@node75 mha]#vim /etc/masterha/app1.cnf

[server default]

user=mhaadmin # MySQL 管理员,用来管理各个节点

password=Pass123456 # MySQL 管理员mhaadmin的密码

manager_workdir=/data/masterha/app1  #这个目录/data/masterha/app1不需要创建,不存在时会自动创建

manager_log=/data/masterha/app1/manager.log 

remote_workdir=/data/masterha/app1 #指各个node节点的工作目录

ssh_user=root #基于密钥连接,所以不需要配置密码

ssh_port=22  #这个选项是全局,如果不定义,就是使用默认的端口22,可以在每个节点上分别再定义端口,基于安全考虑,可以把22端口改成其他的

repl_user=sunnycp 

repl_password=Pass123456

ping_interval=1 #多长时间检测一次

[server1] 

hostname=192.168.1.71 

#ssh_port=22022 #这个选项如果不定义,就是默认的22端口

candidate_master=1 #将来是否可以成为主节点,如果不定义,就不能成为候选的主节点

[server2] 

hostname=192.168.1.76 

#ssh_port=22022 

candidate_master=1 

[server3] 

hostname=192.168.1.77 

#ssh_port=22022 

#no_master=1 #如果定义no_master就不能成为主节点

检测各节点间 ssh 互信通信配置是否 OK:--conf指定配置文件路径

~]# masterha_check_ssh --conf=/etc/masterha/app1.cnf 

输出信息最后一行类似如下信息,表示其通过检测。

[info] All SSH connection tests passed successfully.

检查管理的 MySQL 复制集群的连接配置参数是否 OK:

~]# masterha_check_repl --conf=/etc/masterha/app1.cnf

输出信息如下所示,最后一行的“Health is OK”信息表示通过检测。

Mon Nov 9 17:22:48 2015 - [info] Slaves settings check done.

Mon Nov 9 17:22:48 2015 - [info]

192.168.1.71(192.168.1.71:3306) (current master)

+--192.168.1.76(192.168.1.76:3306)

+--192.168.1.77(192.168.1.77:3306)

 

…… ……


MySQL Replication Health is OK.

启动 MHA,后台运行,注意,masterha_manager没有启动的程序,需要手动启动服务

~]# nohup masterha_manager --conf=/etc/masterha/app1.cnf > /data/masterha/app1/manager.log 2>&1 &

启动成功后,可通过如下命令来查看 master 节点的状态。

~]# masterha_check_status --conf=/etc/masterha/app1.cnf

app1 (pid:4978) is running(0:PING_OK), master:192.168.1.71

上面的信息中“app1 (pid:4978) is running(0:PING_OK)”表示 MHA 服务运行 OK,否则,则会显示为类似“app1 is stopped(1:NOT_RUNNING).”。

如果要停止 MHA,需要使用 masterha_stop 命令。

~]# masterha_stop --conf=/etc/masterha/app1.cnf Stopped app1 successfully.

4.4 测试故障转移

(1) 在 master 节点71关闭 mariadb 服务

~]# killall -9 mysqld mysqld_safe

或者,直接关闭服务

[root@node71 mha]#systemctl stop mariadb;

(2) 在 manager 节点查看日志

/data/masterha/app1/manager.log 日 志 文 件 中 出 现 的 如 下 信 息 , 表 示 manager 检 测 到

192.168.1.71 节点故障,而后自动执行故障转移,将 192.168.1.76 提升为了主节点。

Master 192.168.1.71(192.168.1.71:3306) is down!

Check MHA Manager logs at node75.ghbsunny.cn:/data/masterha/app1/manager.log for details. Started automated(non-interactive) failover.

The latest slave 192.168.1.76(192.168.1.76:3306) has all relay logs for recovery. Selected 192.168.1.76(192.168.1.76:3306) as a new master.

192.168.1.76(192.168.1.76:3306): OK: Applying all logs succeeded. 192.168.1.77(192.168.1.77:3306): This host has the latest relay log events. Generating relay diff files from the latest slave succeeded.

192.168.1.77(192.168.1.77:3306): OK: Applying all logs succeeded. Slave started, replicating from 192.168.1.76(192.168.1.76:3306)

192.168.1.76(192.168.1.76:3306): Resetting slave info succeeded.

Master failover to 192.168.1.76(192.168.1.76:3306) completed successfully.

此时在76上,连接mysql后测试如下

MariaDB [(none)]> show master status;

+-------------------+----------+--------------+------------------+

| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |

+-------------------+----------+--------------+------------------+

| master-log.000004 |      245 |              |                  |

+-------------------+----------+--------------+------------------+

1 row in set (0.00 sec)

但是,slave status没有数据了

MariaDB [(none)]> show slave status;

说明,76已经成为主服务器

注意,故障转移完成后,manager 将会自动停止,因为集群已经不满足条件,所以会停止,需要重新进行设置。此时使用 masterha_check_status 命令检测将会遇到错误提示,如下所示。

]# masterha_check_status --conf=/etc/masterha/app1.cnf 

app1 is stopped(2:NOT_RUNNING).

(3) 提供新的从节点以修复复制集群

原有 master 节点故障后,需要重新准备好一个新的 MySQL 节点。基于来自于 master 节点的备份恢复数据后,将其配置为新的 master 的从节点即可。注意,新加入的节点如果为新增节点,其 IP 地址要配置为原来 master 节点的 IP,否则,还需要修改 app1.cnf 中相应的 ip 地址。随后再次启动 manager,并再次检测其状态。

这里演示将71重新进行修复,将71进行修复后,要修改71的配置文件,因为71已经成为从服务器,需要添加如下的配置后才能重启mysql服务,重新上线

[root@node71 mha]#vim /etc/my.cnf.d/server.cnf 

relay_log_purge = 0 

read_only = 1

[root@node71 mha]#systemctl start mariadb;

重启服务后,当前主节点76不需要做修改,重新上线71后,要在71上指定76为主服务器

连接如mysql

MariaDB [(none)]> change master to master_host='192.168.1.76',master_user='sunnycp',master_password='Pass1234',master_log_file='master-log.000004',master_log_pos=245;

MariaDB [(none)]> start slave;

注意,这里如果71已经故障一段时间,76成为主服务器后已经运行一段时间,则数据会不一样,需要在76备份全量数据还原到71上,然后在重启71的复制线程

71数据恢复完成,且启动复制线程后

在75上检查状态

[root@node75 mha]#masterha_check_repl --conf=/etc/masterha/app1.cnf

正常后,重新启动manager服务

~]# nohup masterha_manager --conf=/etc/masterha/app1.cnf > /data/masterha/app1/manager.log 2>&1 &

检查运行状态

[root@node75 mha]#masterha_check_status --conf=/etc/masterha/app1.cnf

app1 (pid:60043) is running(0:PING_OK), master:192.168.1.76

到这里修复和重新上线mysql节点完成

5  进一步工作

前面三个步骤已经配置了一个基本的 MHA 环境。不过,为了更多实际应用的需求,还需要进一步完成如下操作。

(1) 提供额外检测机制,以名对 master 的监控做出误判;

(2) 在 master 节点上提供虚拟 ip 地址向外提供服务,以名 master 节点转换时,客户端的请求无法正确送达;

(3) 进行故障转移时对原有 master 节点执行 STONITH 操作以避免脑裂; 可通过指定shutdon_script 实现;

(4) 必要时,进行在线 master 节点转换;