MHA高可用集群架构

Posted ღ᭄小艾ヅ࿐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MHA高可用集群架构相关的知识,希望对你有一定的参考价值。

目录:

一、MHA

1.什么是MHA:

2.MHA工作原理:

  • 当master出现故障时,通过对比slave之间io线程读取master上binlog的位置,选取最接近的slave作为最新的slave(laster slave)
  • 其他slave通过与laster slave对比生成差异中继日志,并应用
  • 在laster slave上应用从master保存的binlog,同时将laster slave提升为master
  • 最后在其他slave上应用相应的差异中继日志并开始从新的master开始复制

3.MHA组件:

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

4.MHA组件介绍:

  • MHA Manager:
    运行一些工具,比如masterha_manager工具实现自动监控MySQL Master实现master故障切换,其他工具手动实现master故障切换,在线master转移,连接检查等等。一个Manager可以管理多个master-slave集群
  • MHA Node:
    部署在所有运行MySQL的服务器上,无论是master还是slave。主要有三个作用
    1. 保存二进制日志
      如果能够访问故障master,会拷贝master的二进制日志
    2. 应用差异中继日志
      从拥有最新数据的slave上生成差异中继日志,然后应用差异日志
    3. 清除中继日志
      在不停止SQL线程的情况下删除中继日志

5.MHA工具介绍:

1).Manager工具:

2).Node工具:

  • Node这些工具通常由MHA Manager的脚本触发,无需人工操作

二、MHA部署架构

1.部署规划:

角色ip主机名server-id功能备注
MHA-Manager192.168.74.26mha-manager-管理节点
MHA-Node(Master)192.168.74.27master10数据节点
MHA-Node(Slave1)192.168.74.28slave120数据节点
MHA-Node(Slave2)192.168.74.29slave230数据节点
  • 绑定主机ip和主机名称到/etc/hosts中(四台都需要)
  • 配置epel源:(四台都要)
    进入腾讯镜像站
  • 配置本地自建仓库的yum源(四台都要)
    mkdir -p /soft/mha
    将这个文件上传此目录下,我把需要用到的都下载到这个文件里了
  • vi /etc/yum.repos.d/local.repo
  • 测试MHA依赖软件库的安装:
    yum -y install perl-DBD-MySQL
    perl-Config-Tiny
    perl-Time-HiRes
    perl-Mail-Sender
    perl-Mail-Sendmail
    perl-MIME-Base32
    perl-MIME-Charset
    perl-MIME-EncWords
    perl-Params-Classify
    perl-Params-Validate.x86_64
    perl-Log-Dispatch
    perl-Parallel-ForkManager
    net-tools

2.部署MySQL主从复制环境:

  • 数据库安装位置:/usr/local/mysql
  • 数据库的数据目录:/usr/local/mysql/data
  • 套接字文件:/tmp/mysql.sock
  • 端口:3306
  • 配置文件位置:/usr/local/mysql/my.cnf

1).master主服务器:

  • 第一步:上传mysql软件包
  • 第二步:使用脚本安装MySQL软件
    vi mysql.sh
#!/bin/bash
yum install -y libaio
tar -zxf mysql-5.7.34-linux-glibc2.12-x86_64.tar.gz
mv mysql-5.7.34-linux-glibc2.12-x86_64 /usr/local/mysql
useradd -r -s /sbin/nologin mysql
rm -rf /etc/my.cnf
cd /usr/local/mysql
mkdir mysql-files
chown mysql:mysql mysql-files
chmod 750 mysql-files
bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql &> /root/password.txt
bin/mysql_ssl_rsa_setup --datadir=/usr/local/mysql/data
cp support-files/mysql.server /etc/init.d/mysql
service mysql start
echo 'export PATH=$PATH:/usr/local/mysql/bin' >> /etc/profile
source /etc/profile

然后source这个脚本即可

  • 第三步:设置密码(set password=’******’)
  • 第四步:进行安全初始化
    mysql_secure_installation
  • 第五步:编写master主机中my.cnf配置文件
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
socket=/tmp/mysql.sock
port=3306
log-error=/usr/local/mysql/data/master.err
log-bin=/usr/local/mysql/data/binlog
server-id=10
character_set_server=utf8mb4
gtid-mode=on
log-slave-updates=1
enforce-gtid-consistency

重启mysql

2).slave1,slave2从服务器:

  • 前面步骤同,但是不用进行初始化,通过脚本实现:
#!/bin/bash
yum install -y libaio
mv mysql-5.7.34-linux-glibc2.12-x86_64 /usr/local/mysql
useradd -r -s /sbin/nologin mysql
rm -rf /etc/my.cnf
cd /usr/local/mysql
mkdir mysql-files
chown mysql:mysql mysql-files
chmod 750 mysql-files
cp support-files/mysql.server /etc/init.d/mysql
echo 'export PATH=$PATH:/usr/local/mysql/bin' >> /etc/profile
source /etc/profile
  • 第二步:使用rsync把master服务器中的data数据目录同步到slave1和slave2从服务器中
    现在master中删除rm -rf /usr/local/mysql/data/auto.cnf
    rsync -av /usr/local/mysql/data root@192.168.74.28:/usr/local/mysql/
    rsync -av /usr/local/mysql/data root@192.168.74.29:/usr/local/mysql/
  • 第三步:给slave1和slave2配置my.cnf文件

slave1:

[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
socket=/tmp/mysql.sock
port=3306
log-error=/usr/local/mysql/data/slave1.err
relay-log=/usr/local/mysql/data/relaylog
log-bin=/usr/local/mysql/data/binlog
server-id=20
character_set_server=utf8mb4
log-slave-updates=1
gtid-mode=on
enforce-gtid-consistency
skip-slave-start

slave2:

[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
socket=/tmp/mysql.sock
port=3306
log-error=/usr/local/mysql/data/slave2.err
relay-log=/usr/local/mysql/data/relaylog
log-bin=/usr/local/mysql/data/binlog
server-id=30
character_set_server=utf8mb4
log-slave-updates=1
gtid-mode=on
enforce-gtid-consistency
skip-slave-start
  • 第四步:配置完成后,启动mysql

3.配置主从数据同步:

  • 第一步:在master服务器中创建一个slave同步账号
  • 第二步:创建一个mha账号(方便后期MHA监控主从同步的状态)


  • 第三步:在slave1和slave2中配置主从数据同步(两台slave都配置)


    弄好之后,show slave status\\G查看一下,确保Slave_IO_Running和Slave_SQL_Running都为yes

4.MHA软件的安装:

  • 说明:在所有节点安装mha-node软件包,在mha管理端安装mha-manager软件包
  • 上传软件包到相应的主机,然后使用yum install下载

1).配置ssh互信(免密登入):

  • 说明:
  1. 在生产环境中几乎都是禁止root远程登入服务器的,所以ssh免密登入要在admin用户下进行配置,这是出于安全角度考虑出发
  2. admin用户可以是任意普通用户
  3. 该普通用户用于mha的管理节点远程访问mysql复制组中的所有主机,完成一些其他工作
  • 第一步:在所有机器上创建一个普通账号admin
  • 第二步:配置mha主机到其他主机的admin用户互信
    在mha这台主机上切换到admin用户下

    使用for循环拷贝公钥到其他三台主机上
    然后用ssh连接测试一下
  • ssh免密只需要拷贝公钥,但是以上代码把整个.ssh目录拷贝过去了。
    答:因为MHA的互信,要求不仅仅是MHA免密到master,slave1,slave2,master也要免密到MHA,slave1,slave2…

2).配置admin用户的sudo权限:

master,slave1,slave2三台主机都要(当发生故障时,从服务器也可以自己设置ip):


#User_Alias  表示具有sudo权限的用 户 列表; Host_Alias表示主机的列表
User_Alias MYSQL_USERS = admin
#Runas_Alias  表示用户以什么身份登录
Runas_Alias MYSQL_RUNAS = root
#Cmnd_Alias  表示允许执行命令的列表(命令需使用完整路径)
Cmnd_Alias MYSQL_CMNDS = /sbin/ifconfig,/sbin/arping
MYSQL_USERS ALL = (MYSQL_RUNAS) NOPASSWD: MYSQL_CMNDS
  • 第二步:测试admin用户是否可以挂载vip(只能在master机器上挂载vip
    先切换到admin用户下

3).创建mha相关配置文件:

  • 第一步:在mha服务器上创建工作目录
  • 第二步:创建mha局部配置文件
    vi /etc/mha/app1.cnf
[server default]
# 设置监控用户和密码
user=mha
password=123456
# 设置复制环境中的复制用户和密码
repl_user=slave
repl_password=123456
# 设置ssh的登录用户名
ssh_user=admin
# 设置监控主库,发送ping包的时间间隔,默认是3秒,尝试三次没有回应的时候自动进行failover
ping_interval=3
# 设置mgr的工作目录
manager_workdir=/data/mha/masterha/app1
# 设置mysql master保存binlog的目录,以便MHA可以找到master的二进制日志
master_binlog_dir=/usr/local/mysql/data
# 设置master的pid文件
master_pid_file=/usr/local/mysql/data/master.pid
# 设置mysql master在发生切换时保存binlog的目录(在mysql master上创建这个目录)
remote_workdir=/data/mysql/mha
# 设置mgr日志文件(MHA出现问题,主要看这个日志)
manager_log=/data/mha/masterha/app1/app1-3306.log
# MHA到master的监控之间出现问题,MHA Manager将会尝试从slave1和slave2登录到master上
secondary_check_script=/usr/bin/masterha_secondary_check -s 192.168.74.28 -s 192.168.74.29 --user=admin --port=22 --master_host=192.168.74.27 --master_port=3306
# 设置自动failover时候的切换脚本
master_ip_failover_script="/etc/mha/master_ip_failover.sh 192.168.74.100 1"
# 设置手动切换时候的切换脚本(故障发生时,自动挂载vip到slave1或者slave2)
#master_ip_online_change_script="/etc/mha/master_ip_online_change.sh 192.168.74.100 1"
# 设置故障发生后关闭故障主机脚本
# shutdown_script="/etc/mha/power_manager"
[server1]
hostname=192.168.74.27
port= 3306
candidate_master=1
[server2]
hostname=192.168.74.28
port= 3306
candidate_master=1
[server3]
hostname=192.168.74.29
port= 3307=6
candidate_master=1

4).上传相应脚本/etc/mha目录:

master_ip_failover.sh
脚本内容如下:

#!/usr/bin/env perl

#  Copyright (C) 2011 DeNA Co.,Ltd.
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#  Foundation, Inc.,
#  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

## Note: This is a sample script and is not complete. Modify the script based on your environment.
#!/usr/bin/env perl
#!/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 $gateway = '10.77.133.1';
my $vip  = shift;
#my $bcast = '10.77.133.255';
#my $netmask = '255.255.255.0';
my $interface = 'ens33';
my $key = shift;
#my $ssh_start_vip = "sudo /sbin/ifconfig $interface:$key $vip netmask $netmask && sudo /sbin/arping -f -q -c 5 -w 5 -I $interface -s $vip  -U $gateway";
my $ssh_stop_vip = "sudo /sbin/ifconfig $interface:$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() 
    my $bcast  = `ssh $ssh_user\\@$new_master_host sudo /sbin/ifconfig | grep 'Bcast' | head -1 | awk 'print \\$3' | awk -F":" 'print \\$2'`;
    chomp $bcast;
    my $gateway  = `ssh $ssh_user\\@$new_master_host sudo /sbin/route -n  | grep 'UG' | awk 'print \\$2'`;
    chomp $gateway;
    my $netmask  = `ssh $ssh_user\\@$new_master_host sudo /sbin/ifconfig | grep 'Bcast' | head -1 | awk 'print \\$4' | awk -F":" 'print \\$2'`;
    chomp $netmask;
    my $ssh_start_vip = "sudo /sbin/ifconfig $interface:$key $vip broadcast $bcast netmask $netmask && sudo /sbin/arping -f -q -c 5 -w 5 -I $interface -s $vip  -U $gateway";
    print "=======$ssh_start_vip=================\\n";
    `ssh $ssh_user\\@$new_master_host \\" $ssh_start_vip \\"`;

sub stop_vip() 
    my $ssh_user = "admin";
    print "=======$ssh_stop_vip==================\\n";
    `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";


5).检测ssh互信以及MySQL主从状态:

在mha服务器上切换到admin用户在

  • 检查ssh互信
  • 检查集群状态

6).检查MHA状态,然后运行MHA(监控开始):

MHA:

5.自动Failover测试:

  • 第一步:在master服务器上安装测试工具
    yum install -y sysbench
  • 第二步:插入测试数据
[root@master ~]# sysbench /usr/share/sysbench/oltp_read_only.lua \\
 --mysql-host=192.168.74.27  --mysql-port=3306  --mysql-user=mha \\
 --mysql-password=123456  --mysql-socket=/tmp/mysql.sock \\
 --mysql-db=test  --db-driver=mysql  --tables=1 \\
 --table-size=100000 --report-interval=10 --threads=128 --time=120 prepare
 
mysql> select count(*) from sbtest1;
+----------+
| count(*) |
+----------+
|   100000 |
+----------+
1 row in set (0.01 sec)
  • 第三步:模拟master服务器故障

以上是关于MHA高可用集群架构的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL高可用集群架构-MHA架构

MySQL高可用集群架构——MHA架构

Mysql MHA高可用集群架构

基于半同步复制的MHA高可用MySql集群架构搭建实战

MySQL 高可用集群架构 MHA

构建MHA实现MySQL高可用集群架构