mysql高可用架構MHA搭建(centos7+mysql5.7.28)

不管是傳統行業,仍是互聯網行業,數據可用性都是相當重要的,雖然如今已經步入大數據時代,nosql比較流行,可是做爲數據持久化及事務性的關係型數據庫依然是項目首選,好比mysql。html

如今幾乎全部的公司項目,不說可用性必須達到5個9,至少也要要求,數據庫出現問題,不能丟失數據,可以快速響應異常處理,下面使用mha來搭建mysql高可用集羣(基於centos7+mysql5.7):node

1、MHA簡介mysql

MHA(Master HA)是一款開源的 MySQL 的高可用程序,它爲 MySQL 主從複製架構提供了 automating master failover 功能。MHA 在監控到 master 節點故障時,會提高其中擁有最新數據的 slave 節點成爲新的master 節點,在此期間,MHA 會經過於其它從節點獲取額外信息來避免一致性方面的問題。MHA 還提供了 master 節點的在線切換功能,即按需切換 master/slave 節點。MHA 可以在30秒內實現故障切換,並能在故障切換中,最大可能的保證數據一致性。sql

MHA由兩部分組成:MHA Manager(管理節點)和MHA Node(數據節點)。管理節點能夠單獨部署在一臺獨立的機器上來管理多個master-slave集羣,也能夠部署在一臺slave節點上。數據節點運行在每臺mysql服務器上。Manager會按期檢查master,若出現故障時,會自動將最新數據的slave提高爲新的master,而後將其餘的slave指向新的master。整個故障轉移程序徹底透明。數據庫

目前MHA主要支持一主多從的架構。要搭建MHA,要求一個複製集羣中必須最少有三臺數據庫服務器,一主二從,即一臺充當master,一臺充當備用master,另一臺充當從庫。vim


2、搭建環境架構centos

1.環境配置:bash

  操做系統版本:CentOS7服務器

  MySQL版本:5.7.28架構

  VIP(虛IP):192.168.3.140

  機器列表及功能:

IP hostname server_id 角色及功能
192.168.3.142 s142 142 Monitor Host(監控複製組)/ Master(響應寫請求)
192.168.3.143 s143 143 Candidate Master(響應讀請求)
192.168.3.144 s144 144 Slave(響應讀請求)

 

 

 

 

 

 

3、MHA搭建步驟

1.在s14二、s14三、s144機器上安裝mysql5.7

詳細安裝能夠參照另外一篇文章:centos7安裝mysql-5.7.28 在此再也不詳述

s142 my.cnf配置信息:

[mysqld]
log-bin=/usr/local/mysql/logs/mysql-bin.log
expire-logs-days=1
max-binlog-size=500M
innodb_log_file_size=256M
binlog_format=row server
-id=142 gtid_mode=on enforce_gtid_consistency=1 log_slave_updates=1

 relay_log_recovery=ON
 relay_log=/usr/local/mysql/logs/mysql-relay-bin
 relay_log_index=/usr/local/mysql/logs/mysql-relay-bin.index
 log_error=/usr/local/mysql/logs/mysql-error.log

 #### replication ####
 log_slave_updates=1
 replicate_wild_ignore_table=information_schema.%,performance_schema.%,sys.%

plugin_load="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
loose_rpl_semi_sync_master_enabled=1
loose_rpl_semi_sync_slave_enabled=1
loose_rpl_semi_sync_master_timeout=5000

basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
socket=/usr/local/mysql/mysql.sock
user=mysql
default-storage-engine=InnoDB
character-set-server=utf8
lower_case_table_names = 1
explicit_defaults_for_timestamp=true
[mysqld_safe]
log-error=/usr/local/mysql/mysql-error.log
pid-file=/usr/local/mysql/mysqld.pid
[client]
socket=/usr/local/mysql/mysql.sock
[mysql]
default-character-set=utf8
socket=/usr/local/mysql/mysql.sock

s143 my.cnf配置信息:

[mysqld]
log-bin=/usr/local/mysql/logs/mysql-bin.log
expire-logs-days=1
max-binlog-size=500M
innodb_log_file_size=256M
binlog_format=row server
-id=143 gtid_mode=on enforce_gtid_consistency=1 log_slave_updates=1

 relay_log_recovery=ON
 relay_log=/usr/local/mysql/logs/mysql-relay-bin
 relay_log_index=/usr/local/mysql/logs/mysql-relay-bin.index
 log_error=/usr/local/mysql/logs/mysql-error.log

 #### replication ####
 log_slave_updates=1
 replicate_wild_ignore_table=information_schema.%,performance_schema.%,sys.%

 read_only=1
 relay_log_purge=0

plugin_load="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
loose_rpl_semi_sync_master_enabled=1
loose_rpl_semi_sync_slave_enabled=1
loose_rpl_semi_sync_master_timeout=5000

basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
socket=/usr/local/mysql/mysql.sock
user=mysql
default-storage-engine=InnoDB
character-set-server=utf8
lower_case_table_names = 1
explicit_defaults_for_timestamp=true
[mysqld_safe]
log-error=/usr/local/mysql/mysql-error.log
pid-file=/usr/local/mysql/mysqld.pid
[client]
socket=/usr/local/mysql/mysql.sock
[mysql]
default-character-set=utf8
socket=/usr/local/mysql/mysql.sock

s144 my.cnf 配置信息:

[mysqld]
log-bin=/usr/local/mysql/logs/mysql-bin.log
expire-logs-days=1
max-binlog-size=500M
innodb_log_file_size=256M
binlog_format=row server
-id=144 gtid_mode=on enforce_gtid_consistency=1 log_slave_updates=1

 relay_log_recovery=ON
 relay_log=/usr/local/mysql/logs/mysql-relay-bin
 relay_log_index=/usr/local/mysql/logs/mysql-relay-bin.index
 log_error=/usr/local/mysql/logs/mysql-error.log

 #### replication ####
 log_slave_updates=1
 replicate_wild_ignore_table=information_schema.%,performance_schema.%,sys.%

 read_only=1
 relay_log_purge=0

basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
socket=/usr/local/mysql/mysql.sock
user=mysql
default-storage-engine=InnoDB
character-set-server=utf8
lower_case_table_names = 1
explicit_defaults_for_timestamp=true
[mysqld_safe]
log-error=/usr/local/mysql/mysql-error.log
pid-file=/usr/local/mysql/mysqld.pid
[client]
socket=/usr/local/mysql/mysql.sock
[mysql]
default-character-set=utf8
socket=/usr/local/mysql/mysql.sock

2.建立複製用戶及複製配置

在主節點上配置複製用戶:

create user canal_repl_user;
grant replication slave on *.*  to canal_repl_user identified by '111111';
flush privileges;
grant all on *.* to root identified by '111111'; 

在從節點上執行主從複製命令:

CHANGE MASTER TO
MASTER_HOST='192.168.30.142',
MASTER_PORT=3306,
MASTER_AUTO_POSITION=1,
MASTER_USER='canal_repl_user',
MASTER_PASSWORD='111111';

#master_log_file='master-bin.000001',#5.6後不須要指定
#master_log_pos=189;

#啓動主從複製
START SLAVE

#查看主從複製信息
SHOW SLAVE STATUS

 說明主從複製成功,能夠在主庫中建立一個庫,看看從庫是否同步

 3.在每臺機器上安裝yum源頭及MHA依賴的perl包

wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

  rpm -ivh epel-release-latest-7.noarch.rpm

yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager

如圖安裝成功:

 4.配置ssh免密登陸

分別在s142/s143/s144機器上生成ssh祕鑰:

ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa

將各自公鑰id_rsa.pub發送到另外兩臺機器,並追加到 ~/.ssh/authorized_keys中:

s142:
mv id_rsa.pub id_rsa_142.pub
scp id_rsa_142.pub s143:~/.ssh/
scp id_rsa_142.pub s144:~/.ssh/

s143:
mv id_rsa.pub id_rsa_143.pub
scp id_rsa_143.pub s142:~/.ssh/
scp id_rsa_143.pub s144:~/.ssh/

s144:
mv id_rsa.pub id_rsa_144.pub
scp id_rsa_144.pub s142:~/.ssh/
scp id_rsa_144.pub s143:~/.ssh/
s142:
cat id_rsa_143.pub >> authorized_keys
cat id_rsa_144.pub >> authorized_keys

s143:
cat id_rsa_142.pub >> authorized_keys
cat id_rsa_144.pub >> authorized_keys

s144:
cat id_rsa_143.pub >> authorized_keys
cat id_rsa_142.pub >> authorized_keys

5.安裝MHA 

分別在s14二、s14三、s144上下載node安裝包並安裝:

wget https://qiniu.wsfnk.com/mha4mysql-node-0.58-0.el7.centos.noarch.rpm
rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm

 

 在s142上安裝manager

wget https://qiniu.wsfnk.com/mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
rpm -ivh mha4mysql-manager-0.58-0.el7.centos.noarch.rpm

 

 6.配置MHA Manager

6.1配置全局配置文件

新建 /etc/masterha_default.cnf (必定要是這個路徑,否則後期masterha_check_ssh會提示未找到全局文件)

vim /etc/masterha_default.cnf

[server default]
    user=root
    password=111111
    ssh_user=root
    repl_user=canal_repl_user
    repl_password=111111
    ping_interval=1
    #master_binlog_dir=/usr/local/mysql/logs
    secondary_check_script=masterha_secondary_check -s s142 -s s143 -s s144 
    master_ip_failover_script="/opt/soft/mha/scripts/master_ip_failover"
    master_ip_online_change_script="/opt/soft/mha/scripts/master_ip_online_change"
    report_script="/opt/soft/mha/scripts/send_report"
        

6.2 配置主配置文件

新建/opt/soft/mha/app1/app1.cnf文件,並配置以下信息:

[server default]
manager_workdir=/opt/soft/mha
manager_log=/opt/soft/mha/manager.log

password=111111
user=root

ping_interval=1

repl_password=111111
repl_user=canal_repl_user

#master_binlog_dir=/usr/local/mysql/logs
#secondary_check_script=masterha_secondary_check -s s142 -s s143 -s s144
#master_ip_failover_script="/opt/soft/mha/scripts/master_ip_failover"
#master_ip_online_change_script="/opt/soft/mha/scripts/master_ip_online_change"
#report_script="/opt/soft/mha/scripts/send_report"

#ssh用戶
ssh_user=root

[server1]
hostname=s142
port=3306
master_binlog_dir=/usr/local/mysql/logs
candidate_master=1
check_repl_delay=0

[server2]
hostname=s143
port=3306
master_binlog_dir=/usr/local/mysql/logs
candidate_master=1
check_repl_delay=0

[server3] 
hostname=s144
port=3306
master_binlog_dir=/usr/local/mysql/logs
ignore_fail=1
no_master=1

6.4 配置VIP切換

爲了防止腦裂發生,推薦生產環境採用腳本的方式來管理虛擬 ip,而不是使用 keepalived來完成。

vim /opt/soft/mha/scripts/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
    );

    #定義VIP變量
    my $vip = '192.168.30.140/24';
    my $key = '1';
    my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip";
    my $ssh_stop_vip = "/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";
    }

6.5 配置VIP腳本

vim /opt/soft/mha/scripts/master_ip_online_change

    #!/bin/bash
    source /root/.bash_profile

    vip=`echo '192.168.30.140/24'`  #設置VIP
    key=`echo '1'`

    command=`echo "$1" | awk -F = '{print $2}'`
    orig_master_host=`echo "$2" | awk -F = '{print $2}'`
    new_master_host=`echo "$7" | awk -F = '{print $2}'`
    orig_master_ssh_user=`echo "${12}" | awk -F = '{print $2}'`
    new_master_ssh_user=`echo "${13}" | awk -F = '{print $2}'`

    #要求服務的網卡識別名同樣,都爲ens33(這裏是)
    stop_vip=`echo "ssh root@$orig_master_host /usr/sbin/ifconfig ens33:$key down"`
    start_vip=`echo "ssh root@$new_master_host /usr/sbin/ifconfig ens33:$key $vip"`

    if [ $command = 'stop' ]
      then
        echo -e "\n\n\n****************************\n"
        echo -e "Disabled thi VIP - $vip on old master: $orig_master_host \n"
        $stop_vip
        if [ $? -eq 0 ]
          then
        echo "Disabled the VIP successfully"
          else
        echo "Disabled the VIP failed"
        fi
        echo -e "***************************\n\n\n"
      fi

    if [ $command = 'start' -o $command = 'status' ]
      then
        echo -e "\n\n\n*************************\n"
        echo -e "Enabling the VIP - $vip on new master: $new_master_host \n"
        $start_vip
        if [ $? -eq 0 ]
          then
        echo "Enabled the VIP successfully"
          else
        echo "Enabled the VIP failed"
        fi
        echo -e "***************************\n\n\n"
    fi

6.6.配置報警郵件腳本

首先配置郵件發送設置信息

#mail郵件發送程序,須要先配置好發送這信息
    vim /etc/mail.rc

    set from=qixing@163.com
    set smtp=smtp.163.com
    set smtp-auth-user=qixing
    #拿163郵箱來講這個不是密碼,而是受權碼
    set smtp-auth-password=qixing
    set smtp-auth=login

編寫郵件發送腳本:

   vim /opt/soft/mha/script/send_report


    #!/bin/bash
    source /root/.bash_profile
    # 解析變量
    orig_master_host=`echo "$1" | awk -F = '{print $2}'`
    new_master_host=`echo "$2" | awk -F = '{print $2}'`
    new_slave_hosts=`echo "$3" | awk -F = '{print $2}'`
    subject=`echo "$4" | awk -F = '{print $2}'`
    body=`echo "$5" | awk -F = '{print $2}'`
    #定義收件人地址
    email="qixing@163.com"

    tac /var/log/mha/app1/manager.log | sed -n 2p | grep 'successfully' > /dev/null
    if [ $? -eq 0 ]
        then
        messages=`echo -e "MHA $subject 主從切換成功\n master:$orig_master_host --> $new_master_host \n $body \n 當前從庫:$new_slave_hosts"` 
        echo "$messages" | mail -s "Mysql 實例宕掉,MHA $subject 切換成功" $email >>/tmp/mailx.log 2>&1 
        else
        messages=`echo -e "MHA $subject 主從切換失敗\n master:$orig_master_host --> $new_master_host \n $body" `
        echo "$messages" | mail -s ""Mysql 實例宕掉,MHA $subject 切換失敗"" $email >>/tmp/mailx.log 2>&1  
    fi

6.7 將腳本賦予可執行權限

    chmod +x /opt/soft/mha/scripts/master_ip_failover 
    chmod +x /opt/soft/mha/scripts/master_ip_online_change 
    chmod +x /opt/soft/mha/scripts/send_report

7.驗證MHA配置信息是否正常

7.1 檢查ssh配置:

masterha_check_ssh --conf=/opt/soft/mha/app1/app1.cnf

成功!!!

7.2 檢查主從複製狀況:

masterha_check_repl --conf=/opt/soft/mha/app1/app1.cnf

  健康!!!

8.在master節點上綁定VIP,只需綁定一次,後續會隨主備切換而自動切換

ifconfig ens33:1 192.168.30.140/24

如過遇到問題,需手動刪除,可執行以下命令:

ifconfig ens33:1 del 192.168.30.140

ifconfig ens33:1 down #關閉vip

能夠查看綁定VIP是否成功:

ip addr

 說明綁定成功!

9.在MHA的manager節點上啓動MHA管理進程

nohup masterha_manager --conf=/opt/soft/mha/app1/app1.cnf --ignore_last_failover /opt/soft/mha/app1/manager.log 2>&1 &

命令參數:
--remove_dead_master_conf 該參數表明當發生主從切換後,老的主庫的ip將會從配置文件中移除。 --manger_log 日誌存放位置 --ignore_last_failover 在缺省狀況下,若是MHA檢測到連續發生宕機,且兩次宕機間隔不足8小時的話,則不會進行Failover,之因此這樣限制是爲了不ping-pong效應。該參數表明忽略上次MHA觸發切換產生的文件,默認狀況下,MHA發生切換後會在日誌目錄,也就是上面設置的manager_workdir目錄中產生app1.failover.complete文件,下次再次切換的時候若是發現該目錄下存在該文件將不容許觸發切換,除非在第一次切換後收到刪除該文件,爲了方便,這裏設置爲--ignore_last_failover。

觀察manager.log日誌,查看是否有成功,通常最後打印以下日誌,說明成功:

Thu Jul  2 15:00:05 2020 - [info] Ping(SELECT) succeeded, waiting until MySQL doesn't respond..

10.查看MHA狀態

masterha_check_status --conf=/opt/soft/mha/app1/app1.cnf 

 說明MHA正在運行中,主節點是s142

11.中止MHA管理進程

masterha_stop --conf=/opt/soft/mha/app1/app1.cnf

manager.log日誌會打印終止日誌:

12.手動進行主備切換(在進行手動切換前要先停值manager進程)

masterha_master_switch --conf=/opt/soft/mha/app1/app1.cnf --master_state=alive --new_master_host=s143 --orig_master_is_new_slave --running_updates_limit=10000 --interactive=0

命令參數:

--master_state=dead
強制參數. 可選有: "dead" or "alive". 若是設置爲 alive,將執行在線切主操做。
--dead_master_host=(hostname)
強制參數,--dead_master_ip 和 --dead_master_port 可選。
--interactive=(0|1)
1爲交互模式(默認),會輸入幾個yes;0爲非交互。
--ssh_reachable=(0|1|2)
否經過SSH可達。0表示不可達;2表示未知(默認)。
--skip_change_master
跳過CHANGE MASTER TO 操做
--skip_disable_read_only
跳過在新主上 SET GLOBAL read_only=0的操做。以便稍後手動操做。
--last_failover_minute=(minutes)
最近故障轉移時間間隔(默認480),若是以前的故障轉移是最近完成的(默認狀況下是8小時),MHA Manager不會執行故障轉移,由於問題極可能沒法經過執行故障轉移來解決。此參數的目的是避免乒乓故障轉移問題。您能夠經過更改此參數來更改時間標準
--ignore_last_failover
若是前面的故障轉移失敗,MHA不會啓動故障轉移,由於問題可能會再次發生。啓動故障轉移的正常步驟是手動刪除在(manager_workdir)/(app_name).failover下建立的故障轉移錯誤文件。若是設置該參數,將忽略這個錯誤文件,直接進行故障轉移。
--remove_dead_master_conf
設置此選項後,若是故障轉移成功完成,MHA Manager將自動從配置文件中刪除失效主服務器的部分。
--wait_until_gtid_in_sync(0|1)
適用於GTID模式,設置爲1表示MHA將等待全部slave追上新master的GTID,默認;0表示不等。
--orig_master_is_new_slave
若是原主庫alive,設置該參數,將會使原master做爲新主庫的slave

 說明切換成功!

13.經常使用的命令

SHOW SLAVE STATUS;          #查看從庫複製狀態
SHOW MASTER STATUS;         #查看當前binlog位點
SHOW SLAVE HOSTS;           #查看從庫列表
相關文章
相關標籤/搜索