MHA 简介
MHA(Master High Availability)目前在 MySQL 高可用方面是一个相对成熟的解决方案,它由日本 DeNA 公司的 youshimaton(现就职于 Facebook 公司)开发,是一套优秀的作为 MySQL 高可用性环境下故障切换和主从提升的高可用软件。在 MySQL 故障切换过程中,MHA 能做到在 0~30 秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA 能在最大程度上保证数据的一致性,以达到真正意义上的高可用。
该软件由两部分组成:
- MHA Manager(管理节点):MHA Manager 可以单独部署在一台独立的机器上管理多个 master/slave 集群,也可以部署在一台 slave 节点上;
- MHA Node(数据节点):MHA Node 运行在每台 MySQL 服务器上,MHA Manager 会定时探测集群中的 master 节点,当 master 出现故障时,它可以自动将拥有最新数据的 slave 提升为新的 master,然后将所有其他的 slave 重新指向新的 master。整个故障转移过程对应用程序完全透明;
每个 master/slave 集群称作一个 application,一个 Manager 可以管理多个 application。
在 MHA 自动故障切换过程中,MHA 试图从宕机的主服务器上保存二进制日志,最大程度的保证数据的不丢失,但这并不总是可行的。例如,如果主服务器硬件故障或无法通过 ssh 访问,MHA 没法保存二进制日志,只进行故障转移而丢失了最新的数据。使用 MySQL 5.5 的半同步复制,可以大大降低数据丢失的风险。MHA 可以与半同步复制结合起来。如果只有一个 slave 已经收到了最新的二进制日志,MHA 可以将最新的二进制日志应用于其他所有的 slave 服务器上,因此可以保证所有节点的数据一致性。
目前 MHA 主要支持一主多从的架构。要搭建 MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当 master,一台充当备用 master,另外一台充当从库。因为至少需要三台服务器,出于机器成本的考虑,淘宝也在该基础上进行了改造,目前淘宝 TMHA 已经支持一主一从。
程序组成
MHA 提供了诸多工具程序,下面看一下常见的。
Manager 节点:
masterha_check_ssh
:MHA 依赖的 ssh 环境监测工具;masterha_check_repl
:MYSQL 复制环境检测工具;masterga_manager
:MHA 服务主程序;masterha_check_status
:MHA 运行状态探测工具;masterha_master_monitor
:MYSQL master 节点可用性监测工具;masterha_master_swith
:master 节点切换工具;masterha_conf_host
:添加或删除配置的节点;masterha_stop
:关闭 MHA 服务的工具。
Node 节点:
save_binary_logs
:保存和复制 master 的二进制日志;apply_diff_relay_logs
:识别差异的中继日志事件并应用于其他 slave;purge_relay_logs
:清除中继日志(不会阻塞 SQL 线程);
自定义扩展:
secondary_check_script
:通过多条网络路由检测 master 的可用性;master_ip_failover_script
:更新 application 使用的 masterip;report_script
:发送报告;init_conf_load_script
:加载初始配置参数;master_ip_online_change_script
;更新 master 节点 ip 地址。
工作原理
MHA 工作原理总结流程如下:
- 从宕机崩溃的 master 保存二进制日志事件(binlog events);
- 识别含有最新更新数据的 slave;
- 应用差异的中继日志(relay log)到其他slave;
- 应用从 master 保存的二进制日志事件(binlog events);
- 提升一个 slave 为新 master;
- 使用其他的 slave 连接新的 master 进行复制。
准备环境
本实验环境共有四个节点,其角色分配如下所示:
主机名 | IP | 角色 | Server ID | OS |
---|---|---|---|---|
node1 | 10.0.1.204 | MHA Manager | - | CentOS 7 |
node2 | 10.0.1.200 | MySQL Master | 1 | CentOS 7 |
node3 | 10.0.1.201 | MySQL Slave | 2 | CentOS 7 |
node4 | 10.0.1.202 | MySQL Slave | 3 | CentOS 7 |
做下面操作前请参考「二进制包形式安装MySQL5.7」在 node2、node3 和 node4 上安装好 MySQL。
各节点 /etc/hosts
文件中添加如下内容:
10.0.1.204 node1
10.0.1.200 node2
10.0.1.201 node3
10.0.1.202 node4
初始主节点(node2)的 my.cnf
的 [mysqld]
节下添加如下配置:
server-id=1
log-bin=master-bin
relay-log=relay-bin
从节点(node3、node4)的 my.cnf
的 [mysqld]
节下添加如下配置:
server-id=<按上表填入 Server ID>
relay-log=relay-bin
log-bin=master-bin
# 指定不自动清理 relay log
relay-log-purge=0
# 从节点只读
read-only=1
按上述要求分别配置好主从节点之后,按 MySQL 复制架构的配置方式将其配置完成(可参考「MySQL的主从、主主复制」),并启动 master 节点和各 slave 节点,以及为各 slave 节点启动其 IO 和 SQL 线程,确保主从复制运行无误。
要注意的是,所有 MySQL 节点都必须拥有同一个具有复制权限的用户,因为从节点在主节点挂掉后会被提起来充当主节点。
而后,在所有 MySQL 节点授权拥有管理权限的用户可在本地网络中在其它节点上远程访问。由于此时 slave 节点已经能同步 master 节点的操作了,所以仅需要在 master 节点下执行如下操作即可:
mysql> grant all on *.* to 'mhauser'@'10.0.1.%' identified by '123';
安装配置 MHA
SSH 配置
MHA 集群中的各节点彼此之间需要基于 SSH 互相通信,以实现远程控制及管理功能。简单起见,可在 Manager 节点生成秘钥对,并设置其可远程连接本地主机后,将私钥文件以及 authorized_keys
文件复制给余下的所有节点即可。
在 Manager 节点执行如下操作:
# 生成秘钥对
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:fzjg703Jq3pgWLdCh08nylvnSgT+0IP5Sr1d9PVqIX0 root@centos7-204
The key's randomart image is:
+---[RSA 2048]----+
| |
| |
| .. |
| .+== . |
| =S*++ .. .|
| ..*O++ooo.E|
| .o=Oo=..oo|
| ..+.B.o.. |
| o+*o+.. |
+----[SHA256]-----+
# 将公钥添加到授权文件中
$ cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
# 设置授权文件权限
$ chmod 600 /root/.ssh/authorized_keys
# 拷贝到其它节点
$ scp -rp /root/.ssh node2:/root/
$ scp -rp /root/.ssh node3:/root/
$ scp -rp /root/.ssh node4:/root/
安装 MHA
下载 MHA RPM 包:
mha4mysql-manager
:https://github.com/yoshinorim/mha4mysql-manager/releasesmha4mysql-node
:https://github.com/yoshinorim/mha4mysql-node/releases
在 Manager 节点安装 mha4mysql-manager
:
$ yum localinstall mha4mysql-manager-0.58-0.el7.centos.noarch.rpm -y
在所有 MySQL 节点安装 mha4mysql-node
:
$ yum localinstall mha4mysql-node-0.58-0.el7.centos.noarch.rpm -y
初始化 MHA
Manager 节点需要为每个监控的 master/slave 集群提供一个专用的配置文件,而所有的 master/slave 集群也可共享全局配置。全局配置文件默认为 /etc/masterha_default.cnf
,其为可选配置。如果仅监控一组 master/slave 集群,也可直接通过 application 的配置来提供各服务器默认配置信息。而每个 application 的配置文件路径为自定义,例如,本例中将使用 /etc/masterha/app1.cnf
,其内容如下所示:
[server default]
# MySQL 管理用户
user=mhauser
# MySQL 管理用户密码
password=123
# 工作目录
manager_workdir=/data/masterha/app1
# 日志文件位置
manager_log=/data/masterha/app1/manager.log
# 如果自定义了 binlog 目录,需启用下面配置
# master_binlog_dir=/data/binlog
# 远程工作目录
remote_workdir=/data/masterha/app1
# SSH 用户
ssh_user=root
# MySQL 复制用户
repl_user=repluser
# MySQL 复制用户密码
repl_password=123
# 检测间隔时长,单位为秒
ping_interval=1
[server1]
hostname=10.0.1.200
# ssh_port=22022
# candidate_master 默认为 1,表示该节点可被提升为 master
candidate_master=1
[server2]
hostname=10.0.1.201
[server3]
hostname=10.0.1.202
# no_master 如果启用,则表示该节点不可以被提升为主节点
# no_master=1
检测各节点 SSH 互相通信是否 OK:
$ masterha_check_ssh --conf=/etc/masterha/app1.cnf
Fri May 15 19:39:37 2020 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Fri May 15 19:39:37 2020 - [info] Reading application default configuration from /etc/masterha/app1.cnf..
Fri May 15 19:39:37 2020 - [info] Reading server configuration from /etc/masterha/app1.cnf..
Fri May 15 19:39:37 2020 - [info] Starting SSH connection tests..
Fri May 15 19:39:38 2020 - [debug]
Fri May 15 19:39:37 2020 - [debug] Connecting via SSH from root@10.0.1.200(10.0.1.200:22) to root@10.0.1.201(10.0.1.201:22)..
Fri May 15 19:39:37 2020 - [debug] ok.
Fri May 15 19:39:37 2020 - [debug] Connecting via SSH from root@10.0.1.200(10.0.1.200:22) to root@10.0.1.202(10.0.1.202:22)..
Fri May 15 19:39:37 2020 - [debug] ok.
Fri May 15 19:39:38 2020 - [debug]
Fri May 15 19:39:37 2020 - [debug] Connecting via SSH from root@10.0.1.201(10.0.1.201:22) to root@10.0.1.200(10.0.1.200:22)..
Fri May 15 19:39:37 2020 - [debug] ok.
Fri May 15 19:39:37 2020 - [debug] Connecting via SSH from root@10.0.1.201(10.0.1.201:22) to root@10.0.1.202(10.0.1.202:22)..
Fri May 15 19:39:38 2020 - [debug] ok.
Fri May 15 19:39:39 2020 - [debug]
Fri May 15 19:39:38 2020 - [debug] Connecting via SSH from root@10.0.1.202(10.0.1.202:22) to root@10.0.1.200(10.0.1.200:22)..
Fri May 15 19:39:38 2020 - [debug] ok.
Fri May 15 19:39:38 2020 - [debug] Connecting via SSH from root@10.0.1.202(10.0.1.202:22) to root@10.0.1.201(10.0.1.201:22)..
Fri May 15 19:39:38 2020 - [debug] ok.
Fri May 15 19:39:39 2020 - [info] All SSH connection tests passed successfully.
检查管理的 MySQL 复制集群的连接配置参数是否 OK:
$ masterha_check_repl --conf=/etc/masterha/app1.cnf
...
Testing mysqlbinlog output.. done.
Cleaning up test file(s).. done.
Fri May 15 19:49:38 2020 - [info] Slaves settings check done.
Fri May 15 19:49:38 2020 - [info]
10.0.1.200(10.0.1.200:3306) (current master)
+--10.0.1.201(10.0.1.201:3306)
+--10.0.1.202(10.0.1.202:3306)
...
MySQL Replication Health is OK.
这里可能出现如下报错:
Fri May 15 19:41:08 2020 - [info] Connecting to root@10.0.1.201(10.0.1.201:22).. Can't exec "mysqlbinlog": No such file or directory at /usr/share/perl5/vendor_perl/MHA/BinlogManager.pm line 106. mysqlbinlog version command failed with rc 1:0, please verify PATH, LD_LIBRARY_PATH, and client options at /usr/bin/apply_diff_relay_logs line 532.
此时可通过将对应的节点中的
mysql
、mysqlbinlog
程序软链接到/usr/local/bin/
下解决:$ ln -s /data/app/mysql/bin/mysql /usr/local/bin/ $ ln -s /data/app/mysql/bin/mysqlbinlog /usr/local/bin/
启动 MHA:
$ 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:2069) is running(0:PING_OK), master:10.0.1.200
如上信息则表示主节点为
10.0.1.200
且正常运行中。
如果要停止 MHA,需要使用 masterha_stop
命令:
$ masterha_stop --conf=/etc/masterha/app1.cnf
Stopped app1 successfully.
测试故障转移
在主节点即 node2 中杀掉 MySQL 进程:
$ pkill mysqld
此时 /data/masterha/app1/manager.log
中就会输出如下信息:
----- Failover Report -----
app1: MySQL Master failover 10.0.1.200(10.0.1.200:3306) to 10.0.1.201(10.0.1.201:3306) succeeded
Master 10.0.1.200(10.0.1.200:3306) is down!
Check MHA Manager logs at centos7-204:/data/masterha/app1/manager.log for details.
Started automated(non-interactive) failover.
The latest slave 10.0.1.201(10.0.1.201:3306) has all relay logs for recovery.
Selected 10.0.1.201(10.0.1.201:3306) as a new master.
10.0.1.201(10.0.1.201:3306): OK: Applying all logs succeeded.
10.0.1.202(10.0.1.202:3306): This host has the latest relay log events.
Generating relay diff files from the latest slave succeeded.
10.0.1.202(10.0.1.202:3306): OK: Applying all logs succeeded. Slave started, replicating from 10.0.1.201(10.0.1.201:3306)
10.0.1.201(10.0.1.201:3306): Resetting slave info succeeded.
Master failover to 10.0.1.201(10.0.1.201:3306) completed successfully.
即自动切换主节点为 10.0.1.201
了,可以在 10.0.1.202
主机中使用 show slave status\G;
检查一下。
要注意的是,故障转移完成后 masterha_manager
进程会自动停止,此时使用 masterha_check_status
命令检测将会有如下提示:
$ masterha_check_status --conf=/etc/masterha/app1.cnf
app1 is stopped(2:NOT_RUNNING).
修复集群
原有 master 节点故障后,需要重新准备好一个新的 MySQL 节点。基于来自与 master 节点的备份恢复数据后,将其配置为新的 master 的从节点即可。注意,新加入的节点如果为新增节点,其 IP 地址要配置为原来 master 节点的 IP,否则,还需要修改 app.cnf
中相应节点的 IP 地址,随后再启动 manager:
$ nohup masterha_manager --conf=/etc/masterha/app1.cnf > /data/masterha/app1/manager.log 2>&1 &
并再次检测其状态:
$ masterha_check_status --conf=/etc/masterha/app1.cnf
app1 (pid:3123) is running(0:PING_OK), master:10.0.1.201
注意,新添加的节点需要重复之前从节点的所有操作:
- 安装
masterha-node
;- 在
my.cnf
配置从节点只读、不自动清理 relay log;- 配置 SSH 免密;
- 创建相同的 MySQL 复制用户;
- 创建相同的 MySQL 管理用户;
希望我没有漏什么。。。自己试一下吧~~
更进一步
前面几个步骤已经完成了一个 MHA 基本环境的搭建,不过在实际应用的时候,可能还需要进一步完成如下操作:
- 提供额外检测机制,以免对 master 的监控做出误判;
- 在 master 节点上提供虚拟 IP 地址向外提供服务,以免 master 节点切换时,客户端的请求无法送达;
- 进行故障转移时对原有 master 节点执行 STONITH 操作以避免脑裂,可通过指定
shutdown_script
实现; - 必要时,在线进行 master 节点切换;
这部分内容参见下篇内容「MySQL 高可用——MHA 进阶」。
评论区