MHA集群 MySQL

176 阅读8分钟

一、MHA基础

1、 MHA背景介绍

MHA 是Perl语言写的,开源的MYSQL故障切换方案;全称:Master High Availability,故障切换时间10-30s

有人说,我不要MHA行不行啊; 可以,没问题, 如果主数据库故障了?

首先,你需要手动一个一个地登录上所有的SLAVE从库,然后一个个对比,看谁执行的BINLOG比较新,然后将其作为主库。

接下来,你还需要手动把所有的从库CHANGE MASTER到新选出的主库。

一个字“费劲”!

这要是别的事,也还可以忍,但主库挂掉,会导致业务无法访问,一堆人站你旁边看着你,到时候一紧张再忘记开写了、SLAVE挂不上去,这个影响时间就不是一星半点了;

为了解决上述问题,就有人写了个程序,来执行自动的主从故障切换,这就是MHA;

2、 MHA简介

  MHA(Master High Availability)是由日本人 yoshinorim(原就职于DeNA现就职于FaceBook)开发的一款成熟的、开源的 MySQL 的高可用程序。它为 MySQL 主从复制架构提供了自动故障切换( automating master failover) 功能。 MHA 在监控到 master 节点故障时,会提升其中拥有最新数据的 slave 节点成为新的master 节点,在此期间,MHA 会通过于其它从节点获取额外信息来避免一致性方面的问题,从而在最大程度上保证数据的一致性,以达到真正意义上的高可用,而且整个故障转移过程对应用程序完全透明。最值得称赞的一点是:这一自动故障切换操作,MHA能在10~30秒之内完成

​ 此外,MHA 还提供了 master 节点的在线切换功能,即按需切换 master/slave 节点,大概0.5-2秒内即可完成。

​ 目前MHA主要支持一主多从的架构,要搭建MHA,要求一个复制集群中必须最少有三台数据库服务器,例如一主二从。因为至少需要三台服务器,出于机器成本的考虑,淘宝也在该基础上进行了改造,目前淘宝的TMHA已经支持一主一从。

3、MHA工作原理

MHA的组成

MHA由node和manager组成;

  • MHA Node(数据节点):

相当于监控客户端,所有数据库机器都需要部署node 复制代码

  • MHA Manager(管理节点)

    Manager相当于服务端,MHA Manager会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master,然后将所有其他的slave重新指向新的master(如果原主库恢复,只能当从库)。

    通常单独部署在一台独立机器上管理多个 master/slave 集群(组),每个 master/slave 集群称作一个 application,用来管理统筹整个集群。

    Manager应该尽量避免部署在主库上,否则主机一挂则全挂,不仅主库完蛋了,负责自动迁移的Manager也完蛋了,也没人负责自动故障迁移了,导致架构不可用了。

    可以考虑部署在某一个slave上,此时这台主机挂掉了,只是挂了一个slave,以及Manager,如果此时你不是倒了霉,(主库也挂了),那还不至于架构不可用。但有一点需要注意的是:如果Manager部署在slave上,那么该slave就无法被升级为主库;

image.png

4、MHA的优点总结

  • 自动的故障检测与转移,通常在10-30秒以内;
  • MHA还提供在线主库切换的功能,能够安全地切换当前运行的主库到一个新的主库中(通过将从库提升为主库),大概0.5-2秒内即可完成。
  • 很好地解决了主库崩溃数据的一致性问题
  • 不需要对当前的mysql环境做重大修改
  • 5、不需要在现有的复制框架中添加额外的服务器,仅需要一个manager节点,而一个Manager能管理多套复制,所以能大大地节约服务器的数量;
  • 6、性能优秀,可以工作在半同步和异步复制框架,支持gtid,当监控mysql状态时,仅需要每隔N秒向master发送ping包(默认3秒),所以对性能无影响。你可以理解为MHA的性能和简单的主从复制框架性能一样。
  • 7、只要replication支持的存储引擎都支持MHA,不会局限于innodb
  • 8、对于一般的keepalived高可用,当vip在一台机器上的时候,另一台机器是闲置的,而MHA中并无闲置主机。

二、MHA搭建实验

环境设置:

MHA manager服务器 192.168.37.128

master服务器 192.168.37.101

slave1服务器 192.168.37.133

slave2服务器 192.168.37.135

主从复制需要做好,具体内容在上一篇博客,此处不再赘述

1、配置MHA

在所有服务器上必须先安装 node 组件,最后在 MHA-manager 节点上安装 manager 组件,因为 manager组件 依赖 node 组件。

 ##(1)所有服务器上都安装 MHA 依赖的环境,首先安装 epel 源##
 yum install epel-release --nogpgcheck -y
 ​
 #安装 MHA依赖环境
 yum install -y perl-DBD-MySQL \
 perl-Config-Tiny \
 perl-Log-Dispatch \
 perl-Parallel-ForkManager \
 perl-ExtUtils-CBuilder \
 perl-ExtUtils-MakeMaker \
 perl-CPAN
 ​
 ##(2)安装 MHA 软件包,必须先在所有服务器上安装 node 组件##
 #将安装包上传到/opt/目录中,解压安装node组件##
 cd /opt/
 tar zxvf mha4mysql-node-0.57.tar.gz
 cd mha4mysql-node-0.57
 perl Makefile.PL
 make && make install
 ​
 ##(3)最后在 MHA manager 节点上安装 manager 组件##(manager组件依赖node 组件)
 cd /opt/
 tar zxvf mha4mysql-manager-0.57.tar.gz
 cd mha4mysql-manager-0.57
 perl Makefile.PL
 make && make install

2、在所有服务器上配置无密码认证

 ##(1)在 manager 节点上配置到所有数据库节点的无密码认证
 ssh-keygen -t rsa               #一路按回车键,生成密钥。"-t rsa"指定密钥的类型。
 ssh-copy-id 192.168.37.101   #将公钥传给所有数据库节点,形成免密码连接登录
 ssh-copy-id 192.168.37.133
 ssh-copy-id 192.168.37.135
 ​
 ##(2)在 mysql1 上配置到数据库节点 mysql2 和 mysql3 的无密码认证
 ssh-keygen -t rsa
 ssh-copy-id 192.168.37.133    #将公钥传给两个从节点,形成免密码连接登录
 ssh-copy-id 192.168.37.135
 ​
 ##(3)在 mysql2 上配置到数据库节点 mysql1 和 mysql3 的无密码认证
 ssh-keygen -t rsa
 ssh-copy-id 192.168.37.101
 ssh-copy-id 192.168.37.135
 ​
 ##(4)在 mysql3 上配置到数据库节点 mysql1 和 mysql2 的无密码认证
 ssh-keygen -t rsa
 ssh-copy-id 192.168.37.101
 ssh-copy-id 192.168.37.133

3.manager 节点上配置 MHA

 ##(1)在 manager 节点上复制相关脚本到/usr/local/bin 目录
 cp -rp /opt/mha4mysql-manager-0.57/samples/scripts /usr/local/bin
 #拷贝后会有四个执行文件
 ll /usr/local/bin/scripts/
 ​

 ##(2)复制上述的自动切换时 VIP 的管理脚本到 /usr/local/bin 目录,这里使用master_ip_failover脚本来管理 VIP 和故障切换
 cp /usr/local/bin/scripts/master_ip_failover /usr/local/bin
 ​
 ​
 ##(3)修改内容如下:(删除原有内容,直接复制并修改vip相关参数。可在拷贝前输入 :set paste 解决vim粘贴乱序问题)
 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 = '192.168.37.100';                             #指定vip的地址
 my $brdc = '192.168.37.255';                            #指定vip的广播地址
 my $ifdev = 'ens33';                                    #指定vip绑定的网卡
 my $key = '1';                                          #指定vip绑定的虚拟网卡序列号
 my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip";   #代表此变量值为ifconfig ens33:1 192.168.37.100
 my $ssh_stop_vip = "/sbin/ifconfig ens33:$key down";    #代表此变量值为ifconfig ens33:1 192.168.37.100 down
 my $exit_code = 0;                                      #指定退出状态码为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";
 }

4、 manager节点编辑配置文件

创建 MHA 软件目录并拷贝配置文件,这里使用app1.cnf配置文件来管理 mysql 节点服务器

 mkdir /etc/masterha
 cp /opt/mha4mysql-manager-0.57/samples/conf/app1.cnf /etc/masterha/   #复制配置文件
 ​
 vim /etc/masterha/app1.cnf   #删除原有内容,直接复制并修改节点服务器的IP地址
 [server default]
 manager_log=/var/log/masterha/app1/manager.log
 manager_workdir=/var/log/masterha/app1
 master_binlog_dir=/usr/local/mysql/data
 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_password=123
 repl_user=myslave
 secondary_check_script=/usr/local/bin/masterha_secondary_check -s 192.168.37.133 -s 192.168.37.135
 shutdown_script=""
 ssh_user=root
 user=mha
 ​
 [server1]
 hostname=192.168.37.100
 port=3306
 ​
 [server2]
 candidate_master=1
 check_repl_delay=0
 hostname=192.168.37.133
 port=3306
 ​
 [server3]
 hostname=192.168.37.135
 port=3306

5、第一次配置需要在 Master 节点上手动开启虚拟IP

 /sbin/ifconfig ens33:1 192.168.37.100/24

6、在 manager 节点上测试 ssh 无密码认证

在 manager 节点上测试 ssh 无密码认证,如果正常最后会输出 successfully

masterha_check_ssh -conf=/etc/masterha/app1.cnf

7、在 manager 节点上测试 mysql 主从连接情况

 masterha_check_repl -conf=/etc/masterha/app1.cnf
....
 MySQL Replication Health is OK.     #出现该字样说明主从连接正常

8、在 manager 节点上启动 MHA

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 &

9、在 manager 节点上查看 MHA 状态 和 MHA 日志,可以看到 master的地址

 #查看 MHA 状态,可以看到当前的 master 是 Mysql1 节点。
 masterha_check_status --conf=/etc/masterha/app1.cnf
 ​
 #查看 MHA 日志,也可以看到当前的 master 是 192.168.72.192
 cat /var/log/masterha/app1/manager.log | grep "current master"

三、总结

MHA 的特点

  • 自动故障切换过程中,MHA试图从宕机的主服务器上保存二进制日志,最大程度的保证数据不丢失。
  • 使用半同步复制,可以大大降低数据丢失的风险,如果只有一个slave已经收到了最新的二进制日志,MHA可以将最新的二进制日志应用于其他所有的slave服务器上,因此可以保证所有节点的数据一致性。
  • 目前MHA支持一主多从架构,最少三台服务器,即一主两从。

MHA 的组成

1)MHA Node(数据节点)

MHA Node 运行在每台 MySQL 服务器上。

2)MHA Manager(管理节点)

  • MHA Manager 可以单独部署在一台独立的机器上,管理多个 master-slave 集群;也可以部署在一台 slave 节点上。
  • MHA Manager 会定时探测集群中的 master 节点。当 master 出现故障时,它可以自动将最新数据的 slave 提升为新的 master, 然后将所有其他的 slave 重新指向新的 master。整个故障转移过程对应用程序完全透明。