基於 MHA 高可用的 MySQL

來杯可樂不加糖發表於2019-08-26

功能

1、監控主資料庫伺服器是否可用 

2、當主DB不可用時,從多個從伺服器中選出新的主資料庫伺服器 

3、提供了主從切換和故障轉移功能(可以與半同步複製結合,最大程度的保證資料的完整性)

主從切換過程

1、嘗試從出現故障的主資料庫儲存二進位制日誌 

2、從多個備選從伺服器中選出新的備選主資料庫(使用者可指定不參與選擇的資料庫) 

3、在備選主伺服器和其它從伺服器之間同步差異二進位制資料 

4、新主伺服器應用從原主DB伺服器上儲存的二進位制日誌(若主DB的二進位制儲存下來)     注:重複的主鍵等會使MHA停止進行故障轉移 

5、備選主DB伺服器更新為新的主DB,並更改虛擬IP 

6、遷移叢集中的其它從DB作為新的主DB的從伺服器

架構(支援基於GTID的複製)

步驟

1、配置叢集中所有主機的SSH免認證登入(比如故障轉移過程中儲存原主伺服器二進位制日誌,配置虛擬IP地址等)
2、安裝MHA-node軟體包(所有節點均安裝)和MHA-manager(監控節點安裝)軟體包
   命令:yum -y install perl-Config-Tiny.noarch 
                       perl-Time-HiRes.x86_64
                       perl-Parallel-ForkManager
                       perl-Log-Dispatch-Per.noarch
                       perl-DBD-MySQL ncftp
3、建立主從複製叢集
4、配置MHA管理節點
    使用masterha_check_ssh:檢查ssh免認證登入
    使用masterha_check_repl :檢查複製鏈路
5、啟動並測試MHA服務

例項

1、建立基於GTID複製的叢集
2、開啟ssh免登入認證  
    ssh-keygen #開啟ssh金鑰
    ssh-copy-id -i /root/.ssh/id_rsa -p 22 root@192.168.71.244|223|220   #複製rsa到叢集中的所有伺服器(互相免登入)
    ssh root@192.168.71.244 #驗證是否開啟成功
3、下載node和manager安裝包(wget [url])和安裝perl的支援包(yum -y install perl-DBD-MySQL ncftp per-DBI.x86)
4、安裝node (所有節點)
    rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm
5、安裝manager軟體包和安裝perl支援包(監控節點)
    yum -y install perl-Config-Tiny.noarch            #安裝監控依賴
                       perl-Time-HiRes.x86_64
                       perl-Parallel-ForkManager
                       perl-Log-Dispatch-Per.noarch
                       perl-DBD-MySQL ncftp
    rpm -ivh mha4mysql-manager-0.58-0.el7.centos.noarch.rpm  #安裝監控軟體
6、配置MHA (配置監控節點即可)
       mkdir -p /etc/mha                   #建立MHA配置目錄
       mkdir -p /home/mysql_mha   #建立MHA的工作目錄
       vim /etc/mha/mysql_mha.cnf(見附件1)            #建立配置檔案
7、配置master_ip_failover(見附件2) 並chmod +x /usr/bin/master_ip_failover#變成可執行檔案
8、檢驗ssh登入
        masterha_check_ssh --conf = /etc/mha/mysql_mha.cnf(在監控伺服器中執行)
9、檢驗repl通道
        masterha_check_repl --conf = /etc/mha/mysql_mha.cnf(在監控伺服器中執行)
10、執行mha
    nohup masterha_manager --conf=/etc/mha/mysql_mha.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /home/mysql_mha/manager.log 2>&1 & #放在後臺執行
11、手動配置虛擬IP(在主中配置)
    ifconfig eth0:1 192.168.71.90/24   #ip addr 檢視ip
12、測試(檢視虛擬IP和複製鏈路)
    關閉主,檢視從的複製鏈路和虛擬IP
備註:
#停止MHA
masterha_stop --conf=/etc/mha/mysql_mha.cnf [--remove_dead_master_conf ]--ignore_last_failover < /dev/null > /home/mysql_mha/manager.log 2>&1
#開始MHA
nohup masterha_manager --conf=/etc/mha/mysql_mha.cnf [--remove_dead_master_conf] --ignore_last_failover < /dev/null > /home/mysql_mha/manager.log 2>&1 &
--remove_dead_master_conf:刪除失敗配置

若M當機後,MHA會自動切換
若M重新恢復時,需要再次手動配置主動
CHANGE MASTER TO MASTER_HOST='192.168.71.244', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123456';

MHA常用命令

masterha_manager --conf=/etc/mha/mysql_mha.cnf         #開啟MHA manager
masterha_check_status --conf=/etc/mha/mysql_mha.cnf    #檢查MHA執行狀態
masterha_check_repl --conf=/etc/mha/mysql_mha.cnf      #檢查複製健康狀態
masterha_stop --conf=/etc/mha/mysql_mha.cnf            #停止MHA manager執行
masterha_conf_host --command=add--conf=/etc/mha/mysql_mha.cnf --hostname=db101 --params="no_master=1;ignore_fail=1"                     #在配置檔案中新增或移除host --block 移除
masterha_check——ssh --conf=/etc/mha/mysql_mha.cnf       #ssh認證檢查

【附件1】 mysql_mha.cnf:

[server default]
    user = mha
    password = 123456
    manager_workdir = /home/mysql_mha
    manager_log = /home/mysql_mha/manager.log
    remote_workdir = /home/mysql_mha
    ssh_user = root
    repl_user = repl
    repl_password = 123456
    ping_interval =1
    master_binlog_dir = /usr/local/mysql/log/mysql-bin
    master_ip_failover_script = /usr/bin/master_ip_failover
     #master_ip_online_change_script= /usr/bin/master_ip_online_change
    secondary_check_script = /usr/bin/masterha_secondary_check -s 192.168.71.223 -s 192.168.71.244 -s 192.168.71.220
[server1]
    hostname = 192.168.71.244
    candidate_master = 1
[server2]
    hostname = 192.168.71.223
    candidate_master = 1
[server3]
    hostname = 192.168.71.220
    no_master = 1

【附件2】master_ip_failover

#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
my (
  $command,
  $orig_master_host,$orig_master_ip,$orig_master_port, $orig_master_ssh_port,
  $ssh_user,
  $new_master_host,$new_master_ip,  $new_master_port,  $new_master_user,$new_master_password,$new_master_ssh_port
);
my $vip = '192.168.71.90/24';
my $key = '1';
my $ssh_start_vip = "sudo /sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "sudo /sbin/ifconfig eth0:$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,
  'orig_master_ssh_port=i' => \$orig_master_ssh_port,
  'new_master_host=s'      => \$new_master_host,
  'new_master_ip=s'        => \$new_master_ip,
  'new_master_port=i'      => \$new_master_port,
  'new_master_user=s'      => \$new_master_user,
  'new_master_password=s'  => \$new_master_password,
  'new_master_ssh_port=i'  => \$new_master_ssh_port
);
exit &main();
sub main {
  $ssh_user = defined $ssh_user ? $ssh_user : 'root';
  print "\n\nIN SCRIPT TEST ==== $ssh_user | $ssh_stop_vip == $ssh_user | $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_port 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";
   }

【附件3】 report_script 郵箱通知

#!/usr/bin/perl
use strict;
use warnings FATAL => 'all';

use Email::Simple;
use Email::Sender::Simple qw(sendmail);
use Email::Sender::Transport::SMTP::TLS;
use Getopt::Long;
my ( $dead_master_host, $new_master_host, $new_slave_hosts, $subject, $body );

my $smtp='smtp.qq.com';
my $mail_from='xxx@qq.com';
my $mail_user='xxx@qq.com';
#郵箱授權碼不是密碼 郵箱授權碼獲取方式可以百度
my $mail_auth_pass='xxxxxx';
my $mail_to='xxxxxxxxxx';

GetOptions(
  'orig_master_host=s' => \$dead_master_host,
  'new_master_host=s'  => \$new_master_host,
  'new_slave_hosts=s'  => \$new_slave_hosts,
  'subject=s'          => \$subject,
  'body=s'             => \$body,
);
my $transport = Email::Sender::Transport::SMTP::TLS->new(
    host     => $smtp,
    port     => 25,
    username => $mail_user,
    password => $mail_auth_pass,
);

my $message = Email::Simple->create(
    header => [
        From           => $mail_from,
        To             => $mail_to,
        Subject        => $subject,
    ],
    body => $body,
);

sendmail( $message, {transport => $transport} );
exit 0;

【附圖1】MHA的配置引數
ThinkPHP

【附圖2】masterha_check_ssh --conf = /etc/mha/mysql_mha.cnf 結果:

【附圖3】masterha_check_repl --conf=/etc/mha/mysql_mha.cnf 結果:

來杯可樂不加糖。

相關文章