5人参与 • 2025-10-27 • Mysql
mha 是一套优秀的、开源的 mysql 高可用性解决方案。它的核心目标是在 mysql 主从复制环境中,实现主库故障时的自动故障转移和快速切换,尽可能保证数据库服务的连续性。
一个典型的 mha 集群包含以下组件:
mha 的工作原理可以概括为:一个聪明的“大脑”(manager)时刻监控着整个 mysql 集群,一旦“首领”(master)倒下,它会立刻根据数据的新旧程度选出一个最合适的“新首领”,并设法找回“老首领”没来得及交代的“遗言”(未同步的日志),最终让所有“部下”(slaves)效忠于“新首领”,从而快速恢复秩序。
mha 的工作流程可以分为两大阶段:日常监控阶段 和 故障转移阶段。
select 1 之类的简单查询来检查它们的存活状态。这个阶段,manager 对整个集群的健康状况和结构了如指掌。
当 manager 检测到主库无法连接或已经宕机时,它会自动触发故障转移流程。这个过程非常精细,是其高可靠性的关键。
第1步:验证主库故障
第2步:选择新的主库
第3步:补偿丢失的数据(关键步骤)
第4步:切换从库到新主库
change master to ...)。第5步:虚拟 ip 切换(可选但常用)
第6步:通知管理员(可选)
至此,整个故障转移过程完成,集群恢复了服务。
实验思路:
1.mha架构
1)数据库安装
2)一主两从
3)mha搭建
2.故障模拟
1)主库失效
2)备选主库成为主库
3)原故障主库恢复重新加入到mha成为从库
架构图

节点服务器 所需服务及组件 ip地址 主机名
| 角色 | 安装组件 | ip地址 | 主机名 |
|---|---|---|---|
| mha manager | 安装mha node 和 manager 组件 | 192.168.4.54 | host54 |
| master | 安装mysql5.7、mha node 组件 | 192.168.4.51 | host51 |
| slave1 | 安装mysql5.7、mha node 组件 | 192.168.4.52 | host52 |
| slave2 | 安装mysql5.7、mha node 组件 | 192.168.4.53 | host53 |
关闭防火墙,selinux
systemctl stop firewalld systemctl disable firewalld setenforce 0
分别编辑主机名
hostnamectl set-hostname host51 #4.51主机上执行 hostnamectl set-hostname host52 #4.52主机上执行 hostnamectl set-hostname host53 #4.53主机上执行 hostnamectl set-hostname host54 #4.54主机上执行
编辑所有节点的 /etc/hosts 文件,添加以下内容
echo "192.168.4.51 host51" >> /etc/hosts echo "192.168.4.52 host52" >> /etc/hosts echo "192.168.4.53 host53" >> /etc/hosts echo "192.168.4.54 host54" >> /etc/hosts
示范在host51节点安装,另外两个节点同理
[root@host51 ~]# tar -xvf mysql-5.7.17.tar #v:显示详细信息
[root@host51 ~]# yum -y install mysql-community-*.rpm
[root@host51 ~]# systemctl restart mysqld #启动服务
[root@host51 ~]# systemctl enable mysqld
[root@host51 ~]# ss -antlp | grep 3306
[root@host51 ~]# ps -c mysqld #查看进程连接数据库
使用初始密码登录
[root@host51 ~]# grep password /var/log/mysqld.log #获取初始密码
#重置密码
[root@host51 ~]# mysqladmin -uroot -p'qg1wpz;g+deg' password '123qqq...a'
[root@host51 ~]# mysql -uroot -p123qqq...a在 mha manager 节点上生成密钥对,并分发到所有 mysql 节点。
[root@host54 ~]# ssh-keygen -f /root/.ssh/id_rsa -n '' [root@host54 ~]# ssh-copy-id root@host51 [root@host54 ~]# ssh-copy-id root@host52 [root@host54 ~]# ssh-copy-id root@host53
mha manager 需要通过 ssh 连接到所有 mysql 节点执行管理命令(如启动、停止、复制状态检查等),免密登录是必须的。
数据库节点之间也必须配置 ssh 免密码登录,这是 mha 正常工作的关键要求。
[root@host51 ~]# ssh-keygen -f /root/.ssh/id_rsa -n '' [root@host51 ~]# ssh-copy-id root@host52 [root@host51 ~]# ssh-copy-id root@host53 [root@host52 ~]# ssh-keygen -f /root/.ssh/id_rsa -n '' [root@host52 ~]# ssh-copy-id root@host51 [root@host52 ~]# ssh-copy-id root@host53 [root@host53 ~]# ssh-keygen -f /root/.ssh/id_rsa -n '' [root@host53 ~]# ssh-copy-id root@host51 [root@host53 ~]# ssh-copy-id root@host52
在mysqld下添加两行
[mysqld] server_id=51 log_bin=master51 relay-log-purge = 0 # 禁止自动删除中继日志(控制是否自动删除不再需要的中继日志)
重启mysqld服务
systemctl restart mysqld
mysql> grant replication slave on *.* to repluser@"%" identified by '123qqq...a'; query ok, 0 rows affected, 1 warning (0.01 sec) mysql> show master status; +-----------------+----------+--------------+------------------+-------------------+ | file | position | binlog_do_db | binlog_ignore_db | executed_gtid_set | +-----------------+----------+--------------+------------------+-------------------+ | master51.000001 | 441 | | | | +-----------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec)
在mysqld下添加server_id
host52:
[mysqld] server_id=52 log_bin=master52 relay-log-purge = 0 # 禁止自动删除中继日志(控制是否自动删除不再需要的中继日志)
host53:
[mysqld] server_id=53 log_bin=master53 relay-log-purge = 0 # 禁止自动删除中继日志(控制是否自动删除不再需要的中继日志)
重启mysqld服务
[root@host52 ~]# systemctl restart mysqld [root@host53 ~]# systemctl restart mysqld
host52:
mysql> change master to master_host='192.168.4.51',master_user='repluser',master_password='123qqq...a',master_log_file='master51.000001',master_log_pos=441;
query ok, 0 rows affected, 2 warnings (0.02 sec)
mysql> start slave;
query ok, 0 rows affected (0.00 sec)
mysql> show slave status\g;
*************************** 1. row ***************************
slave_io_state: waiting for master to send event
master_host: 192.168.4.51
master_user: repluser
master_port: 3306
connect_retry: 60
master_log_file: master51.000001
read_master_log_pos: 441
relay_log_file: host52-relay-bin.000002
relay_log_pos: 319
relay_master_log_file: master51.000001
slave_io_running: yes
slave_sql_running: yes
....................host53:
mysql> change master to master_host="192.168.4.51",master_user="repluser",master_password="123qqq...a",master_log_file="master51.000001",master_log_pos=441;
query ok, 0 rows affected, 2 warnings (0.02 sec)
mysql> start slave;
query ok, 0 rows affected (0.01 sec)
mysql> show slave status\g;
*************************** 1. row ***************************
slave_io_state: waiting for master to send event
master_host: 192.168.4.51
master_user: repluser
master_port: 3306
connect_retry: 60
master_log_file: master51.000001
read_master_log_pos: 441
relay_log_file: host53-relay-bin.000002
relay_log_pos: 319
relay_master_log_file: master51.000001
slave_io_running: yes
slave_sql_running: yes
.................... 在所有slave节点也授权
grant replication slave on *.* to repluser@"%" identified by "123qqq...a";
mha node 需要在所有 mysql 数据库节点上安装
mha node 是运行在每台 mysql 服务器上的代理。
mha-node资源包网址:
https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-node-0.58-0.el7.centos.noarch.rpm
# 安装依赖 # 如果 ncftp 不可用,可以跳过 [root@host51 mysql]# yum -y install perl-dbd-mysql ncftp perl-dbix-simple [root@host52 mysql]# yum -y install perl-dbd-mysql nfctp perl-dbix-simple [root@host53 mysql]# yum -y install perl-dbd-mysql nfctp perl-dbix-simple # 使用 yum 安装 mha node [root@host51 mysql]# yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm [root@host52 mysql]# yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm [root@host53 mysql]# yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm
mha node 包含了 save_binary_logs, apply_diff_relay_logs 等关键脚本,用于故障切换时保存和应用日志。
为什么需要 epel?
perl-parallel-forkmanager、perl-config-inifiles、ncftp 这些包在 centos 默认仓库中不可用
epel 仓库提供了这些额外的软件包
先启用 epel 可以避免 “no package available” 错误
注意!下载epel仓库需要联网,可以给manage节点设置双网卡,其中一个网卡设置为nat模式
下载 epel 的 rpm 包
epel 的官方地址可能会变,但你可以去这个链接下载最新的适用于 centos 7 的 epel 包:
安装包下载:https://pan.quark.cn/s/956399e9b728
启用 epel 仓库 yum -y install epel-release-latest-7.noarch.rpm yum clean all yum repolist
仅在 mha-manager 节点上执行
mha manager 是管理核心。
mha-manager资源包网址:
https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
mha-node资源包网址:
https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-node-0.58-0.el7.centos.noarch.rpm
# 安装依赖 yum install -y perl-dbd-mysql perl-config-inifiles perl-time-hires perl-parallel-forkmanager ncftp perl-log-dispatch perl-dbi mha4mysql-node-0.58-0.el7.centos.noarch.rpm yum -y install mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
manager 会监控 node 的状态,并在 master 故障时协调故障切换过程
创建 mha 工作目录和配置文件
在 mha-manager 节点上操作。
mkdir -p /etc/mha mkdir -p /var/log/mha
创建主配置文件 /etc/mha/app1.cnf:
[server default] # [server default] 段 - 全局默认配置 # mysql 用户和密码 # mha manager 连接 mysql 节点时使用的用户名和密码 # 需要在所有 mysql 节点上创建这个用户并授予相应权限 user=mha password=123qqq...a # mysql 主从复制使用的用户名和密码 # 用于在故障切换时在新主库上配置复制关系 repl_user=repluser repl_password=123qqq...a # ssh 配置 ssh_user=root # mha manager 工作目录 manager_workdir=/var/log/mha manager_log=/var/log/mha/manager.log # 远程工作目录(在 mysql 节点上) remote_workdir=/var/log/mha # 主从复制相关配置 ping_interval=3 # 二次检查,防止脑裂 secondary_check_script=masterha_secondary_check -s host52 -s host53 -s host51 master_binlog_dir=/var/lib/mysql # 故障切换脚本(可选) #master_ip_failover_script=/etc/mha/master_ip_failover [server1] hostname=host51 candidate_master=1 [server2] hostname=host52 candidate_master=1 [server3] hostname=host53 no_master=1 # 这个节点永远不会被提升为新的 master
解释:
[server default]:全局默认配置。
secondary_check_script:非常重要,通过多个 slave 来确认 master 是否真的宕机,防止网络分区导致的脑裂。
candidate_master=1:优先级高,在故障切换时优先被提升为新主。
no_master=1:标记该节点不应被提升为主库(例如,配置较低或用于备份)。
在master主库授权mha用户
mysql> grant all on *.* to mha@"%" identified by '123qqq...a'; query ok, 0 rows affected, 1 warning (0.03 sec)
# 检查 ssh 连接 masterha_check_ssh --conf=/etc/mha/app1.cnf # 检查主从复制状态 masterha_check_repl --conf=/etc/mha/app1.cnf
mkdir -p /var/log/mha nohup masterha_manager --conf=/etc/mha/app1.cnf < /dev/null > /var/log/mha/manager.log 2>&1 &
[root@host54 ~]# masterha_check_status --conf=/etc/mha/app1.cnf app1 (pid:12835) is running(0:ping_ok), master:host51
自动切换过程
mha 检测到 master 宕机
自动选择最优 slave(host52)提升为新 master
其他 slave(host53)重新指向新 master
mha manager 记录切换日志并自动停止
停止 host51 的 mysql 服务
在master节点执行 systemctl stop mysqld
在 host54 上验证 [root@host54 ~]# tail -f /var/log/mha/manager.log started automated(non-interactive) failover. the latest slave host52(192.168.4.52:3306) has all relay logs for recovery. selected host52(192.168.4.52:3306) as a new master. host52(192.168.4.52:3306): ok: applying all logs succeeded. host53(192.168.4.53:3306): this host has the latest relay log events. generating relay diff files from the latest slave succeeded. host53(192.168.4.53:3306): ok: applying all logs succeeded. slave started, replicating from host52(192.168.4.52:3306) host52(192.168.4.52:3306): resetting slave info succeeded. master failover to host52(192.168.4.52:3306) completed successfully.
[root@host53 mysql]# mysql -h host52 -u mha -p123qqq...a -e "show master status" mysql: [warning] using a password on the command line interface can be insecure. +-----------------+----------+--------------+------------------+-------------------+ | file | position | binlog_do_db | binlog_ignore_db | executed_gtid_set | +-----------------+----------+--------------+------------------+-------------------+ | master52.000001 | 441 | | | | +-----------------+----------+--------------+------------------+-------------------+
[root@host52 mysql]# mysql -h host53 -u mha -p123qqq...a -e "show slave status\g"
mysql: [warning] using a password on the command line interface can be insecure.
*************************** 1. row ***************************
slave_io_state: waiting for master to send event
master_host: 192.168.4.52
master_user: repluser
master_port: 3306
connect_retry: 60
master_log_file: master52.000001
read_master_log_pos: 441
relay_log_file: host53-relay-bin.000002
relay_log_pos: 319
relay_master_log_file: master52.000001
slave_io_running: yes
slave_sql_running: yes
.............................. 在新主库 host52 上插入数据
mysql> show databases;
+--------------------+
| database |
+--------------------+
| information_schema | |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql> create database d2;
query ok, 1 row affected (0.02 sec)
mysql> create table d2.student(name char(10),number int default 10);
query ok, 0 rows affected (0.02 sec)
mysql> insert into d2.student values("bob",1);
query ok, 1 row affected (0.01 sec)在从库 host53 上验证数据同步
mysql> show databases; +--------------------+ | database | +--------------------+ | information_schema | | | d2 | | mysql | | performance_schema | | sys | +--------------------+ 6 rows in set (0.00 sec) mysql> select * from d2.student; +------+--------+ | name | number | +------+--------+ | bob | 1 | +------+--------+ 1 row in set (0.00 sec)
因为在host51宕机期间,现在的master节点插入了数据,它们之间有数据差异,所以这里需要先同步数据
备份数据
[root@host52 ~]# mysqldump -uroot -p123456 --all-databases --master-data=1 > backup.sql [root@host52 ~]# scp backup.sql host51:/root/
host51同步数据
[root@host51 ~]# systemctl start mysqld [root@host51 ~]# mysql -uroot -p123456 < backup.sql [root@host51 ~]# mysql -uroot -p123456 mysql> show databases; +--------------------+ | database | +--------------------+ | information_schema | | | d2 | | | mysql | | performance_schema | | sys | +--------------------+ 7 rows in set (0.00 sec) mysql> select * from d2.student; +------+--------+ | name | number | +------+--------+ | bob | 1 | +------+--------+ 1 row in set (0.00 sec)
查看当前master host52的status
mysql> show master status; +-----------------+----------+--------------+------------------+-------------------+ | file | position | binlog_do_db | binlog_ignore_db | executed_gtid_set | +-----------------+----------+--------------+------------------+-------------------+ | master52.000001 | 1046 | | | | +-----------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec)
host51配置为当前 master 的从库:
-- 在旧 master 上执行
mysql> change master to master_host="192.168.4.52", master_user="repluser", master_password="123qqq...a", master_log_file="master52.000001", master_log_pos=1046;
query ok, 0 rows affected, 2 warnings (0.01 sec)
mysql> start slave;
query ok, 0 rows affected (0.01 sec)
mysql> show slave status\g;
*************************** 1. row ***************************
slave_io_state: waiting for master to send event
master_host: 192.168.4.52
master_user: repluser
master_port: 3306
connect_retry: 60
master_log_file: master52.000001
read_master_log_pos: 1046
relay_log_file: host51-relay-bin.000002
relay_log_pos: 319
relay_master_log_file: master52.000001
slave_io_running: yes
slave_sql_running: yes在host52上插入数据
mysql> create database d3;
query ok, 1 row affected (0.01 sec)
mysql> create table d3.student(name char(10),number int default 10);
query ok, 0 rows affected (0.02 sec)
mysql> insert into d3.student values("tom",2);
query ok, 1 row affected (0.00 sec)在host51上检查数据
mysql> select * from d3.student; +------+--------+ | name | number | +------+--------+ | tom | 2 | +------+--------+ 1 row in set (0.01 sec)
到此,mha高可用集群搭建完毕
到此这篇关于mysql mha 高可用集群搭建指南的文章就介绍到这了,更多相关mysql mha 高可用集群内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论