MySQL数据库 MHA高可用配置及故障处理

MHA概述

MHA(Master High Availability)目前在 MySQL 高可用方面是一个相对成熟的解决方案,它由日本 DeNA 公司的 youshimaton(现就职于 Facebook 公司)开发,是一套优秀的作为 MySQL 高可用性环境下故障切换和主从提升的高可用软件。
在 MySQL 故障切换过程中,MHA 能做到在0~30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA 能在最大程度上保证数据的一致性,以达到真正意义上的高可用。
该软件由两部分组成:MHA Manager(管理节点)和 MHA Node(数据节点)。MHA Manager 可以单独部署在一台独立的机器上管理多个 master-slave 集群,也可以部署在一台 slave 节点上。MHA Node 运行在每台 MySQL 服务器上,MHA Manager 会定时探测集群中的 master 节点,当 master 出现故障时,它可以自动将最新数据的 slave 提升为新的 master,然后将所有其他的 slave 重新指向新的 master。整个故障转移过程对应用程序完全透明。
在 MHA 自动故障切换过程中,MHA 试图从宕机的主服务器上保存二进制日志,最大程度的保证数据的不丢失,但这并不总是可行的。例如,如果主服务器硬件故障或无法通过ssh访问,MHA 没法保存二进制日志,只进行故障转移而丢失了最新的数据。使用 MySQL 的半同步复制,可以大大降低数据丢失的风险。MHA 可以与半同步复制结合起来。如果只有一个 slave 已经收到了最新的二进制日志,MHA 可以将最新的二进制日志应用于其他所有的 slave 服务器上,因此可以保证所有节点的数据一致性。
目前 MHA 主要支持一主多从的架构,要搭建 MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当 master,一台充当备用 master,另外一台充当从库,因为至少需要三台服务器,出于机器成本的考虑,淘宝也在该基础上进行了改造,目前淘宝TMHA已经支持一主一从。

MHA组成

MHA Manager(管理节点)
用来接收外部信号,监控下方数据节点的工作状态
MHA Node(数据节点)
工作的单位,负责具体的工作

MHA特点

自动故障切换过程中,MHA试图从宕机的主服务器上保存二进制日志,最大程度的保证数据的不丢失
使用 MySQL55的半同步复制,可以大大降低数据丢失的风险

在这里插入图片描述
不过传统架构中,只有一个mysql主服务器,所以当出现单点故障的时候,整个服务器群集就会瘫痪掉
为了解决这种情况,我们需要在主服务器宕机的时候,重新建立一台主服务器,负责监控等工作

来吧!展示!!

在这里插入图片描述
master 20.0.0.5
slave01 20.0.0.6
slave02 20.0.0.7

编译安装MySQL

编译安装mysql,因为我们使用的系统是CentOS 7,所以使用与之相兼容的mah 0.5.7,mysql使用最适配的 mysql5.6

yum -y install ncurses \
ncurses \
bison \
cmake \
gcc \
ncurses-devel \
gcc-c++

tar zxvf mysql-5.6.26.tar.gz
cd mysql-5.6.26/
cmake \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_EXTRA_CHARSETS=all \
-DSYSCONFDIR=/etc
make && make install

复制配置文件和服务启动脚本

[root@5centos mysql-5.6.26]# cp support-files/my-default.cnf /etc/my.cnf
cp:是否覆盖"/etc/my.cnf"? y
[root@5centos mysql-5.6.26]# cp support-files/mysql.server /etc/rc.d/init.d/mysqld

添加mysqld服务

[root@5centos mysql-5.6.26]# chmod +x /etc/rc.d/init.d/mysqld
[root@7CentOS mysql-5.6.26]# chkconfig --add mysqld

添加环境变量

[root@5centos mysql-5.6.26]# echo "PATH=$PATH:/usr/local/mysql/bin" >> /etc/profile
[root@5centos mysql-5.6.26]# source /etc/profile

添加程序运行用户

[root@5centos mysql-5.6.26]# groupadd mysql
[root@5centos mysql-5.6.26]# useradd -M -s /sbin/nologin mysql -g mysql
[root@5centos mysql-5.6.26]# chown -R mysql.mysql /usr/local/mysql

初始化数据库

/usr/local/mysql/scripts/mysql_install_db \
--basedir=/usr/local/mysql \
--datadir=/usr/local/mysql/data \
--user=mysql

修改Matser配置文件

[root@5centos mysql-5.6.26]# vim /etc/my.cnf
server-id = 1	##三台MySQLserver-id不能一样
log_bin = master-bin
log-slave-updates = true

修改slave01、slave02配置文件

[root@localhost mysql-5.6.26]# vim /etc/my.cnf
server-id = 2  ##02我写的3
log_bin = master-bin
relay-log = relay-log-bin
relay-log-index = slave-relay-bin.index
[root@7CentOS mysql-5.6.26]# systemctl restart mysqld

三台均启动服务

ln -s /usr/local/mysql/bin/mysql /usr/sbin/
ln -s /usr/local/mysql/bin/mysqlbinlog /usr/sbin/
/usr/local/mysql/bin/mysqld_safe --user=mysql &

进入数据库

[root@5centos mysql-5.6.26]# mysql -u root -p
Enter password:   ##仅实验,所以懒一点使用空密码
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.6.26-log Source distribution

Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

配置远程登录

GRANT ALL ON *.* TO 'remote_user'@'%' IDENTIFIED BY 'abc123';

配置主从服务

mysql_slave用于数据库主从同步
mha_manager用于manager连接MySQL

mysql> GRANT REPLICATION SLAVE ON *.* TO 'mysql_slave'@'20.0.0.%'  IDENTIFIED BY 'abc123';
Query OK, 0 rows affected (0.00 sec)
mysql> GRANT ALL PRIVILEGES ON *.* TO 'mha_manager'@'20.0.0.%'  IDENTIFIED BY 'abc123';
Query OK, 0 rows affected (0.00 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

下面三条授权按理论是不用添加的,但是做实验环境时候通过检查MySOL主从有报错,报两个从库通过主机名连接不上主库,所以所有数据库加上下面的授权

mysql> GRANT ALL PRIVILEGES ON *.* TO 'mha_manager'@'master' IDENTIFIED BY 'abc123';
Query OK, 0 rows affected (0.00 sec)
mysql> GRANT ALL PRIVILEGES ON *.* TO 'mha_manager'@'slave1' IDENTIFIED BY 'abc123';
Query OK, 0 rows affected (0.00 sec)
mysql> GRANT ALL PRIVILEGES ON *.* TO 'mha_manager'@'slave2' IDENTIFIED BY 'abc123';
Query OK, 0 rows affected (0.00 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

查看master状态

mysql> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000001 |     1739 |              |                  |                   |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

设置从服务

mysql> CHANGE MASTER TO MASTER_HOST='20.0.0.5', MASTER_USER='mysql_slave', MASTER_PASSWORD='abc123', MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=1739;
Query OK, 0 rows affected, 2 warnings (0.01 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
            ……省略部分……
            Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

设置两个从库为只读

mysql> set global read_only=1;
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)

安装MHA

所有服务器安装node,包括之前没用到的MHA
安装所需依赖

[root@localhost bao]# yum install epel-release --nogpgcheck -y
[root@localhost bao]# yum install -y perl-DBD-MySQL \
> perl-Config-Tiny \
> perl-Log-Dispatch \
> perl-Parallel-ForkManager \
> perl-ExtUtils-CBuilder \
> perl-ExtUtils-MakeMaker \
> perl-CPAN

编译安装node

[root@localhost bao]# tar zxvf mha4mysql-node-0.57.tar.gz 
[root@localhost bao]# cd mha4mysql-node-0.57/
perl Makefile.PL
make &&make install

编译安装manager,只装在MHA上

[root@localhost mha4mysql-node-0.57]# cd ..
[root@localhost bao]# tar zxvf mha4mysql-manager-0.57.tar.gz
[root@localhost mha4mysql-manager-0.57]# perl Makefile.PL
[root@localhost mha4mysql-manager-0.57]# make&&make install

manager安装后在/usr/local/bin下面会生成几个工具,主要包括以下几个:
masterha_check_ssh 检查MHA的SSH 配置状况
masterha_check_repl检查MySQL复制状况
masterha_manger启动manager的脚本
masterha_check_status检测当前MHA运行状态
masterha_master_monitor检测master是否宕机
masterha_master_switch 控制故障转移(自动或者手动)
masterha_conf_host 添加或删除配置的server信息
masterha_stop关闭manager

node安装后也会在/usr/local/bin下面会生成几个脚本(这些工具通常由MHA Manager的脚本触发,无需人为操作)主要如下:
save_binary_logs保存和复制master的二进制日志
purge_relay_logs清除中继日志(不会阻塞SQL线程)
apply_diff_relay_logs识别差异的中继日志事件并将其差异的事件应用于其他的slave
filter_mysqlbinlog去除不必要的ROLLBACK事件(MHA已不再使用这个工具)

[root@localhost mha4mysql-manager-0.57]# cd /usr/local/bin/
[root@localhost bin]# ls
apply_diff_relay_logs  masterha_conf_host        masterha_stop
filter_mysqlbinlog     masterha_manager          purge_relay_logs
masterha_check_repl    masterha_master_monitor   save_binary_logs
masterha_check_ssh     masterha_master_switch
masterha_check_status  masterha_secondary_check

SSH配置

MHA

[root@localhost bin]# ssh-keygen -t rsa
##然后回车,最后按y
[root@localhost bin]# ssh [email protected]
[root@localhost bin]# ssh [email protected]
[root@localhost bin]# ssh [email protected]

master

ssh-keygen -t rsa
ssh [email protected]
ssh [email protected]

slave01

ssh-keygen -t rsa
ssh [email protected]
ssh [email protected]

slave02

ssh-keygen -t rsa
ssh [email protected]
ssh [email protected]

配置MHA-Manager组件

##在mha节点上复制相关脚本到/usr/local/bin目录
[root@mha ~]# cp -ra /root/mha4mysql-manager-0.57/samples/scripts /usr/local/bin
[root@mha ~]# ll /usr/local/bin/scripts/
总用量 32
-rwxr-xr-x. 1 1001 1001  3648 5月  31 2015 master_ip_failover ##自动切换时 VIP管理的脚本
-rwxr-xr-x. 1 1001 1001  9870 5月  31 2015 master_ip_online_change ##在线切换VIP的管理
-rwxr-xr-x. 1 1001 1001 11867 5月  31 2015 power_manager ##故障发生后关闭主机的脚本
-rwxr-xr-x. 1 1001 1001  1360 5月  31 2015 send_report ##因故障切换后发送报警的脚本
[root@mha ~]# cp /usr/local/bin/scripts/master_ip_failover /usr/local/bin/ ##自动切换时 VIP管理的脚本

修改master_ip_failover 脚本

[root@mha ~]# vim /usr/local/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 = '20.0.0.200';      ##浮动路由的ip地址
my $brdc = '20.0.0.255';     ##广播地址
my $ifdev = 'ens33';              ##网卡名
my $key = '1';
my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig ens33:$key down";
my $exit_code = 0;
#my $ssh_start_vip = "/usr/sbin/ip addr add $vip/24 brd $brdc dev $ifdev label $ifdev:$key;/usr/sbin/arping -q -A -c 1 -I $ifdev $vip;iptables -F;";
#my $ssh_stop_vip = "/usr/sbin/ip addr del $vip/24 dev $ifdev label $ifdev:$key";
#########################################################
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 \"`;
}
# A simple system call that disable the VIP on the old_master
sub stop_vip() {
    
    
`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";
}

创建MHA软件目录并拷贝配置文件

[root@mha ~]# cd /usr/local/bin/scripts/
[root@mha scripts]# cp master_ip_online_change /usr/local/bin/
[root@mha scripts]# cp send_report /usr/local/
[root@mha scripts]# mkdir /etc/masterha
[root@mha ~]# cp /root/mha4mysql-manager-0.57/samples/conf/app1.cnf /etc/masterha
[root@mha ~]# vim /etc/masterha/app1.cnf  ##删除内容,重新填写
[server default]
manager_log=/var/log/masterha/app1/manager.log  ##manager日志
manager_workdir=/var/log/masterha/app1    ##manager工作目录
master_binlog_dir=/usr/local/mysql/data    ##master保存binlog的位置,这里的路径要与master里配置的binlog的路径一直,以便mha能找到
master_ip_failover_script=/usr/local/bin/master_ip_failover  ##设置自动failover时候的切换脚本,也就是上边的那个脚本
master_ip_online_change_script=/usr/local/bin/master_ip_online_change ##设置手动切换时候的切换脚本
password=manager  ##设置mysql中root用户的密码,这个密码是前文中创建监控用户的那个密码
ping_interval=1  ##设置监控主库,发送ping包的时间间隔,默认是3秒,尝试三次没有回应的时候自动进行rail
remote_workdir=/tmp  ##设置远端mysql在发生切换时binlog的保存位置
repl_password=123  ##设置复制用户的密码
repl_user=myslave   ##设置复制用户的用户
secondary_check_script=/usr/local/bin/masterha_secondary_check -s 20.0.0.6 -s 20.0.0.7 ##设置从服务器的地址
shutdown_script="" ##设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机放在发生脑裂,这里没有使用)'
ssh_user=root  ##设置ssh的登录用户名
user=mha

[server1]
hostname=20.0.0.5
port=3306

[server2]
candidate_master=1  ##设置为候选master
hostname=20.0.0.6
check_repl_delay=0  ##默认情况下如果一个slave落后master 100M的relay logs 的话,mha将不会选择该slave作为一个新的master
port=3306

[server3]
hostname=20.0.0.7
port=3306

测试SSH无密码验证

SSH无密码验证,正常最后会输出successfully

[root@mha ~]# masterha_check_ssh -conf=/etc/masterha/app1.cnfThu Aug 27 23:19:44 2020 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Thu Aug 27 23:19:44 2020 - [info] Reading application …省略部分…
Thu Aug 27 23:19:51 2020 - [info] All SSH connection tests passed successfully.

验证mysql复制,mysql必须都启动

[root@mha ~]# masterha_check_repl -conf=/etc/masterha/app1.cnf
IN SCRIPT TEST====/sbin/ifconfig ens33:1 down==/sbin/ifconfig ens33:1 20.0.0.200===

Checking the Status of the script.. OK 
Thu Aug 27 23:21:00 2020 - [info]  OK.
Thu Aug 27 23:21:00 2020 - [warning] shutdown_script is not defined.
Thu Aug 27 23:21:00 2020 - [info] Got exit code 0 (Not master dead).

MySQL Replication Health is OK.

启动MHA

第一次配置需要去master上手动开启虚拟ip

[root@mysql1 ~]# /sbin/ifconfig ens33:1 20.0.0.200/24
[root@mha ~]# masterha_check_status --conf=/etc/masterha/app1.cnf
app1 (pid:65368) is running(0:PING_OK), master:20.0.0.5

查看mysql1的VIP地址20.0.0.200是否存在,这个VIP地址不会因为mha节点停止mha服务而消失

[root@mysql1 ~]# ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 20.0.0.5  netmask 255.255.255.0  broadcast 20.0.0.255
        inet6 fe80::1301:89f0:4405:2aad  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:a9:8d:f9  txqueuelen 1000  (Ethernet)
        RX packets 9588  bytes 10245457 (9.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4708  bytes 579551 (565.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 20.0.0.200  netmask 255.255.255.0  broadcast 20.0.0.255
        ether 00:0c:29:a9:8d:f9  txqueuelen 1000  (Ethernet)

进行验证

查看监控观察日志

[root@mha ~]# tailf /var/log/masterha/app1/manager.log

模拟故障

[root@mysql1 ~]# pkill -9 mysql

查看200地址

[root@mysql2 ~]# ifconfig 
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 20.0.0.6  netmask 255.255.255.0  broadcast 20.0.0.255
        inet6 fe80::1301:89f0:4405:2aad  prefixlen 64  scopeid 0x20<link>
        inet6 fe80::769:c122:2af2:c353  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:c2:17:3b  txqueuelen 1000  (Ethernet)
        RX packets 9714  bytes 10234408 (9.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5441  bytes 741224 (723.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 20.0.0.200  netmask 255.255.255.0  broadcast 20.0.0.255
        ether 00:0c:29:c2:17:3b  txqueuelen 1000  (Ethernet)

猜你喜欢

转载自blog.csdn.net/Ora_G/article/details/108265112