赞
踩
目录
MHA全称是MySQL Master High Availability,它是一款开源的高可用程序,专门为MySQL的主从复制架构设计,提供了自动化的主节点故障转移功能。
本案例要求通过 MHA 监控 MySQL 数据库在故障时进行自动切换,不影响业务。
主机 | 操作系统 | IP 地址 | 角色 |
服务器 | CentOS7.9 | 192.168.10.101 | 管理节点,安装 node、manager 组件 |
服务器 | CentOS7.9 | 192.168.10.102 | Master 节点,安装 node 组件 |
服务器 | CentOS7.9 | 192.168.10.103 | Slave 节点,安装 node 组件 |
服务器 | CentOS7.9 | 192.168.10.104 | Slave 节点,安装 node 组件 |
测试机 | CentOS7.9 | 192.168.10.105 | 作为客户端测试结果 |
打开除了测试机的其他四台作为服务器的主机,都连接上XShell
因为接下来有相同操作,右键终端空白处给4台数据库主机都开启会话同步
使用disable永久关闭防火墙,修改selinux文件来永久关闭内核安全机制,为了实现每个主机都能通过名称的方式互相通信,在hosts文件末尾追加以下内容
- [root@localhost ~]# systemctl stop firewalld
- [root@localhost ~]# systemctl disable firewalld
- [root@localhost ~]# setenforce 0
- [root@localhost ~]# vim /etc/sysconfig/selinux
- SELINUX=disabled # 修改参数为disabled
- [root@localhost ~]# vim /etc/hosts
- 192.168.10.101 MHA-manager
- 192.168.10.102 Mysql1
- 192.168.10.103 Mysql2
- 192.168.10.104 Mysql3
- # 保存并退出
此时需要安装数据库,而101作为管理服务器的角色,用不到数据库所以不用安装,把101的会话同步关掉,然后安装数据库软件包
此时会话同步的主机应该是102、103、104,101是关闭会话同步的
在102输入
使用yum为3个主从服务器安装mariadb服务端
[root@localhost ~]# yum -y install mariadb-server
修改mysql的配置文件,在[mysqld]单元下方添加以下内容
- [root@localhost ~]# vim /etc/my.cnf
- [mysqld]
- server-id=102
- log-bin=master-bin
- binlog-format=MIXED
- relay-log-purge=0
- log-slave-updates=true
因为开着会话同步,但是server-id的参数又不能重复,所以先关闭全部会话同步,然后修改另外两个主机的server-id
- # 103主机改为:
- server-id=103
- # 104主机改为:
- server-id=104
然后再开启会话同步,和刚才一样,把101的会话同步关闭,只同步三台服务器的会话
在102输入
启动mariadb数据库,设置密码,然后登录进去
- [root@Mysql1 ~]# systemctl start mariadb
- [root@Mysql1 ~]# mysqladmin -uroot password 'pwd123'
使用grant语句授权给从服务器可以访问所有库的所有表
MariaDB [(none)]> grant replication slave on *.* to 'myslave'@'192.168.10.%' identified by '123456';
指定网段和主机名的连接权限
MHA是整个架构的管理者,所以授权设为all,因为mha的权限很大。所以mha的权限应该授权给装有MHA的主机来使用
如果要基于IP地址来连接:可以指定为IP地址
如果要基于主机名来连接:可以指定为主机名,比如:'mha'@'Mysql1'
如果觉得192.168.10.0的网段范围太大了,可以单独指定多个IP设置
- MariaDB [(none)]> grant all privileges on *.* to 'mha'@'192.168.10.%' identified by 'manager';
- MariaDB [(none)]> grant all privileges on *.* to 'mha'@'Mysql1' identified by 'manager';
- MariaDB [(none)]> grant all privileges on *.* to 'mha'@'Mysql2' identified by 'manager';
- MariaDB [(none)]> grant all privileges on *.* to 'mha'@'Mysql3' identified by 'manager';
- MariaDB [(none)]> flush privileges; # 刷新权限
输入完上方的语句就可以关闭会话同步了
在实现高可用多主复制之前,要由MHA程序来确定,在安装MHA之前,要先部署出一个普通的主从架构
在102输入
这里我们先让102主机作为主服务器,使用show命令查看主服务器上的二进制日志的状态信息,以便后续使用
- MariaDB [(none)]> show master status;
- +-------------------+----------+--------------+------------------+
- | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
- +-------------------+----------+--------------+------------------+
- | master-bin.000003 | 1196 | | |
- +-------------------+----------+--------------+------------------+
在103、104输入
这里102和103的操作是一样的,所以再开启会话同步,但是注意只同步103和104两个从服务器的输入
使用change语句修改主从复制的参数设置,指定主服务器的IP、连接的用户、密码、二进制日志文件名、二进制日志文件中语句的位置
这里使用的二进制日志名和位置,就是刚才在102主服务器使用show master status;查询到的信息
然后开启从服务器的复制(start slave;)再使用show命令查看从服务器的状态信息,确保IO线程和SQL线程状态都是YES
- MariaDB [(none)]> change master to master_host='192.168.10.102', master_user='myslave', master_password='123456', master_log_file='master-bin.000003', master_log_pos=1196;
- MariaDB [(none)]> start slave;
- MariaDB [(none)]> show slave status\G;
- Slave_IO_Running: Yes
- Slave_SQL_Running: Yes
关闭会话同步
确保所有主机都在终端界面,如果在数据库内的终端,要使用quit命令回到bash终端并且直接输入cd命令回到root用户家目录
然后再次同步所有主机的会话输入,注意是所有主机
在101操作
把下图的软件包导入进每个主机中
因为需要安装MHA所需要的依赖环境,所以这里把仓库源换成阿里云的yum仓库
直接把下方的四行命令全部复制,然后粘贴到终端里回车
- rm -rf /etc/yum.repos.d/*
- curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
- curl -o /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
- yum clean all
使用yum命令安装所以相关依赖软件包,如下
yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker perl-CPAN
安装完后,解压刚才导入的mha软件包,然后cd进入解压目录
- [root@MHA-manager ~]# tar zxvf mha4mysql-node-0.57.tar.gz
- [root@MHA-manager ~]# cd mha4mysql-node-0.57
使用perl命令执行perl脚本,目的是生成一个名为 Makefile 的文件。这个 Makefile 包含了安装和编译所需的指令
然后编译,安装。注意检查4个会话同步的主机是否操作正常
- [root@MHA-manager mha4mysql-node-0.57]# perl Makefile.PL
- [root@MHA-manager mha4mysql-node-0.57]# make && make install
- [root@MHA-manager mha4mysql-node-0.57]# cd # 回到root用户家目录
因为要通过MHA在其他节点之间进行通信和操作,实现免密登录时为了可以安全而无缝(快速响应)的远程操作和管理
所以需要在所有主机上都生成密钥对,此时的会话同步不用改变
- [root@MHA-manager ~]# ssh-keygen -t rsa
- # 回车直到显示终端,密钥对生成成功
此时关闭所有会话同步
因为接下来的操作不一致,步骤繁琐
还是在MHA服务器(101)操作
使用ssh-copy-id指定要发送公钥的主机IP,交互界面输入yes,再输入该主机的密码
- [root@MHA-manager ~]# ssh-copy-id 192.168.10.102
- [root@MHA-manager ~]# ssh-copy-id 192.168.10.103
- [root@MHA-manager ~]# ssh-copy-id 192.168.10.104
来到主服务器(102)操作
步骤同上,拷贝公钥到两个从服务器
- [root@Mysql1 ~]# ssh-copy-id 192.168.10.103
- [root@Mysql1 ~]# ssh-copy-id 192.168.10.104
来到1号从服务器(103)操作
步骤同上,拷贝公钥到主服务器和2号从服务器
- [root@Mysql2 ~]# ssh-copy-id 192.168.10.102
- [root@Mysql2 ~]# ssh-copy-id 192.168.10.104
来到2号从服务器(104)操作
步骤同上,拷贝公钥到主服务器和1号从服务器
- [root@Mysql3 ~]# ssh-copy-id 192.168.10.102
- [root@Mysql3 ~]# ssh-copy-id 192.168.10.103
在104主机连接102和103,如果都是直接登录进去,就说明免密登录实现成功了
- [root@mysql3 ~]# ssh 192.168.10.102
- [root@mysql1 ~]# exit
- [root@mysql3 ~]# ssh 192.168.10.103
- [root@mysql2 ~]# exit
回到MHA服务器(101)操作
导入MHA的manager组件到MHA服务器(101)准备安装
解压、进入解压目录、配置、编译、安装
- [root@MHA-manager ~]# tar zxvf mha4mysql-manager-0.57.tar.gz
- [root@MHA-manager ~]# cd mha4mysql-manager-0.57
- [root@MHA-manager mha4mysql-manager-0.57]# perl Makefile.PL
- [root@MHA-manager mha4mysql-manager-0.57]# make && make install
在manager解压目录下,samples目录下的scripts目录,存放着管理脚本,作用分别如下
这里的VIP指的是一个虚拟IP,这个IP是整个MySQL的集群对外的一个IP,在集群中,哪个主机时master就用这个IP
最后拷贝这些脚本到/usr/local/bin目录下,能够方便的在终端使用脚本
- [root@MHA-manager mha4mysql-manager-0.57]# cd samples
- [root@MHA-manager samples]# cd scripts/
- [root@MHA-manager scripts]# ls
- master_ip_failover master_ip_online_change power_manager send_report
- [root@MHA-manager scripts]# cp * /usr/local/bin/
cd进入/usr/local/bin目录下,打开刚才拷贝过来的文件
- [root@MHA-manager scripts]# cd /usr/local/bin/
- [root@MHA-manager bin]# vim master_ip_failover
把以下内容全部替换到master_ip_failover文件中
因为vim编辑器会在上一行带有#的情况下,为下方复制的所有行也添加#注释。
所以先单独复制指定解释器的这一行,再复制下方内容。或者使用vi编辑器而不是vim编辑器复制
#!/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.10.200/24';
- my $key = '1';
- my $ssh_start_vip = "/usr/sbin/ifconfig ens33:$key $vip up";
- my $ssh_stop_vip = "/usr/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";
- &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";
- }

首先在/etc/下创建一个用于放置配置文件的目录,然后在manager解压目录的samples/conf目录下,拷贝app1配置文件到刚才创建的masterha目录,然后打开拷贝过去的该文件
- [root@MHA-manager bin]# cd /etc
- [root@MHA-manager etc]# mkdir masterha
- [root@MHA-manager etc]# cd /root/mha4mysql-manager-0.57/samples/conf/
- [root@MHA-manager conf]# cp app1.cnf /etc/masterha/
- [root@MHA-manager conf]# vim /etc/masterha/app1.cnf
把下方内容全部替换到app1.cnf文件中
其中的工作目录,我们的系统中还没有,所以mkdir -p /var/log/masterha/app1创建出来
- [server default]
- manager_workdir=/var/log/masterha/app1
- manager_log=/var/log/masterha/app1/manager.log
- master_binlog_dir=/var/lib/mysql
- master_ip_failover_script= /usr/local/bin/master_ip_failover
- master_ip_online_change_script= /usr/local/bin/master_ip_online_change
- user=mha
- password=manager
- ping_interval=1
- remote_workdir=/tmp
- repl_user=myslave
- repl_password=123456
- secondary_check_script= /usr/local/bin/masterha_secondary_check -s 192.168.10.103 -s 192.168.10.104
- shutdown_script=""
- ssh_user=root
- [server1]
- hostname=192.168.10.102
- port=3306
- [server2]
- hostname=192.168.10.103
- port=3306
- candidate_master=1
- check_repl_delay=0
- [server3]
- hostname=192.168.10.104
- port=3306

同样的内容,下方是一些对应注释
注意:下方带注释的内容不要复制进app1.cnf中,可能会影响配置文件的使用
- [server default]
- manager_workdir=/var/log/masterha/app1 # 工作目录,如果没有需要创建出来
- manager_log=/var/log/masterha/app1/manager.log # 生成的日志文件名
- #master_binlog_dir=/usr/local/mysql/data
- master_binlog_dir=/var/lib/mysql # 日志文件位置
- master_ip_failover_script= /usr/local/bin/master_ip_failover # 指定自动切换VIP脚本的位置
- master_ip_online_change_script= /usr/local/bin/master_ip_online_change # 指定在线切换VIP脚本的位置
- user=mha # 对应之前在主服务器授权给mha的用户
- password=manager # 对应之前在主服务器授权给mha用户的密码
- ping_interval=1
- remote_workdir=/tmp
- repl_user=myslave # 主从复制连接用的用户
- repl_password=123456 # 主从复制连接的密码
- secondary_check_script= /usr/local/bin/masterha_secondary_check -s 192.168.10.103 -s 192.168.10.104 # 指定脚本,检查作为备用的两个从主机的状态
- shutdown_script=""
- ssh_user=root
- [server1] # 对应主服务器
- hostname=192.168.10.102
- port=3306
- [server2] # 对应从服务器
- hostname=192.168.10.103
- port=3306
- candidate_master=1 # 如果master故障了,优先候选的master是[server2]
- check_repl_delay=0 # 检查复制延迟,0表示忽略
- [server3] # 对应从服务器
- hostname=192.168.10.104
- port=3306

保存并退出
使用命令测试ssh的免密登录,如果正常会输出下方代码块最后一行内容
这里如果出错了,一般就是免密登录有问题或者app1.cnf的文件配置有问题
- [root@MHA-manager ~]# masterha_check_ssh -conf=/etc/masterha/app1.cnf
- Fri Aug 2 10:53:05 2024 - [info] All SSH connection tests passed successfully. # 出现这行表示成功
测试mysql主从连接的情况,如果正常会输出下方代码块最后一行内容
这里如果出错哦了,有可能是授权或配置文件出问题了,可以去数据库使用show slave status;查看状态来排除
- [root@MHA-manager ~]# masterha_check_repl -conf=/etc/masterha/app1.cnf
- MySQL Replication Health is OK. # 出现这行表示成功
这里配置的IP是刚才在配置文件中指定的VIP,由于这个IP我们还没有定义出来,所以需要先创建出来
在102操作
因为虚拟IP是会随着master的变更而转移的,所以直接创建一个临时的子接口就行了
使用ifconfig命令创建一个临时的子接口,指定接口IP为192.168.10.200,然后使用ifconfig查看是否创建成功
- [root@Mysql1 ~]# ifconfig ens33:1 192.168.10.200
- [root@Mysql1 mysql]# ifconfig
- ens33:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
- inet 192.168.10.200 netmask 255.255.255.0 broadcast 192.168.10.255
在101操作
启动MHA 管理器,并且以后台进程的方式运行,同时将日志记录到指定的文件中,忽略任何可能的标准输入,并配置好在发现主服务器不可用时自动移除,并忽略最后一次故障转移的历史记录
[root@MHA-manager ~]# nohup masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf --ignore_last_failover </dev/null> /var/log/masterha/app1/manager.log 2>&1 &
参数 | 说明 |
nohup | 全称 no hang up(不挂起),用于在系统后台不挂起地运行命令,退出终端不会影响程序的运行。 |
--conf | 指定配置文件的路径 |
--remove_dead_master_conf | 当发生主从切换后,老的主库的 IP 地址将会从配置文件中移除 确保MHA不会继续尝试连接已经不可用的主服务器 |
--ignore_last_failover | 这个选项告诉MHA忽略最后一次故障转移的历史记录。 在某些情况下,如果你希望MHA不考虑上一次的故障转移事件,可以使用这个选项。 |
进程可能会在终端需要输入时挂起,或者受到其他影响,通过将命令的标准输入重定向都/dev/null 确保命令不会等待终端输入,而是在后台继续运行。 | |
/var/log/masterha/app1/manager.log | 日志文件绝对路径 |
2>&1 | 表示将标准输出和错误输出都重定向到manager.log |
& | 末尾的&,表示在后台运行 |
启动后,使用masterha_check_status命令检查mha的状态
- [root@MHA-manager ~]# masterha_check_status --conf=/etc/masterha/app1.cnf
- app1 (pid:1533) is running(0:PING_OK), master:192.168.10.102 # 出现这行表示正在运行,当前的master是102主机
如果要查看日志信息,可以cat之前的配置文件中指定的生成路径
[root@MHA-manager ~]# cat /var/log/masterha/app1/manager.log
先打开作为测试机的主机,并连接上XShell
在105(测试机)操作
连接整个集群的VIP,能正常连接,接下来模拟故障
- [root@localhost ~]# yum -y install mysql
- [root@localhost ~]# mysql -umha -pmanager -h 192.168.10.200
- MariaDB [(none)]> show databases;
在101(MHA)操作
首先来到101主机使用tail -f来动态显示mha日志文件的末尾十行内容,等会102故障时,立刻去101主机看日志的变化
[root@mha-manager masterha]# tail -f /var/log/masterha/app1/manager.log
要测试主备切换的话,需要出现故障才会进行切换,所以这里先模拟一个故障
在102(master)操作
来到Master主机,关闭数据库服务,
[root@Mysql1 ~]# systemctl stop mariadb
在101(MHA)操作
查看日志文件的变化
- [root@MHA-manager ~]# tail /var/log/masterha/app1/manager.log
- Invalidated master IP address on 192.168.10.102(192.168.10.102:3306) # 发现master地址无效
- The latest slave 192.168.10.103(192.168.10.103:3306) has all relay logs for recovery. # 指出了候选的从服务器,具有所有用于恢复的中继日志
- Selected 192.168.10.103(192.168.10.103:3306) as a new master. # 选择新的主服务器,192.168.10.103:3306升级为新的主服务器
- 192.168.10.103(192.168.10.103:3306): OK: Applying all logs succeeded. # 新的主服务器成功应用了所有的日志。
- 192.168.10.103(192.168.10.103:3306): OK: Activated master IP address. # 新的主服务器的IP地址激活成功。
- 192.168.10.104(192.168.10.104:3306): This host has the latest relay log events. # 指出另一台服务器192.168.10.104:3306有最新的中继日志事件
- Generating relay diff files from the latest slave succeeded. # 从最新的从服务器成功生成了中继日志的差异文件。
- # 服务器192.168.10.104成功应用了所有的日志,并且作为从服务器开始复制数据,数据源是192.168.10.103。
- 192.168.10.104(192.168.10.104:3306): OK: Applying all logs succeeded. Slave started, replicating from 192.168.10.103(192.168.10.103:3306)
- # 服务器192.168.10.103成功重置了从服务器的信息
- 192.168.10.103(192.168.10.103:3306): Resetting slave info succeeded.
- # 主服务器的故障切换到192.168.10.103成功完成
- Master failover to 192.168.10.103(192.168.10.103:3306) completed successfully.
在102(原master)操作
使用ifconfig查看此时的102(原master)的接口信息,可以发现192.168.10.200不见了
[root@mysql1 ~]# ifconfig
在103(现master)操作
使用ifconfig查看接口信息,可以看到vip的192.168.10.200来到了103主机
- [root@mysql2 ~]# ifconfig
- ens33:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
- inet 192.168.10.200 netmask 255.255.255.0 broadcast 192.168.10.255
那么我们就可以得知,vip(Vrtual IP)在哪个主机,哪个主机就是master服务器
在103(现master)操作
103已经不是从服务器了,所以关闭复制的线程(stop slave;)
再重置103之前作为从服务器的复制配置和状态
目的是:假如有一天103故障了,修好以后又作为从服务器运行时,103会开始全新的复制过程,以便进行新一轮的测试或开发工作。
- MariaDB [(none)]> stop slave;
- MariaDB [(none)]> reset slave;
- MariaDB [(none)]> show master status;
- +-------------------+----------+--------------+------------------+
- | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
- +-------------------+----------+--------------+------------------+
- | master-bin.000003 | 1196 | | |
- +-------------------+----------+--------------+------------------+
在102操作
如果原本的master服务器(102)的故障被修好了,102并不能接替现在的master成为主服务器,只能当做现master服务器(103)的从服务器去存在,所以这里需要为102配置作为从服务器相关设置
配置102作为从服务器连接主服务器(103)的参数,启动复制进程,查看状态确保IO线程和SQL线程正常启动
注意change语句指定的二进制日志文件和位置,是要跟现master服务器的状态信息一致的(master-bin.000004、245)
- MariaDB [(none)]> change master to master_host='192.168.10.103', master_user='myslave', master_password='123456', master_log_file='master-bin.000003', master_log_pos=1196;
- MariaDB [(none)]> start slave;
- MariaDB [(none)]> show slave status\G;
- Slave_IO_Running: Yes
- Slave_SQL_Running: Yes
作为从服务器,应该只有读取数据(select)的权利,所以这里设置为只读
MariaDB [(none)]> set global read_only=1;
如果此时去104(第二个从服务器)
登录进数据库,查看slave的状态信息,可以发现master的IP也变成了103(先master)而不是102(原master)了
- MariaDB [(none)]> show slave status\G;
- Master_Host: 192.168.10.103
在105操作
最后再去测试机测试,案例完成
- MariaDB [(none)]> show databases;
- +--------------------+
- | Database |
- +--------------------+
- | information_schema |
- | mysql |
- | performance_schema |
- | test |
- +--------------------+
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。