1. 程式人生 > 實用技巧 >MHA實現MySQL主從複製高可用

MHA實現MySQL主從複製高可用

一、MHA介紹

1.1 MHA概述

  • 一套優秀的作為MySQL高可用性環境下故障切換和主從提升的高可用軟體
  • 支援故障切換
  • 在MySQL故障切換過程中,MHA能做到在0~30秒之內自動完成資料庫的故障切換操作,並且在進行故障切換的過程中,MHA能在最大程度上保證資料的一致性,以達到真正意義上的高可用

1.2 MHA組成

  • MHA Manager(管理節點)
    • 用來接收外部訊號,監控下方資料節點的工作狀態
  • MHA Node(資料節點)
    • 工作的單位,負責具體的工作

1.3 MHA的特點

  • 自動故障切換過程中,MHA試圖從宕機的主伺服器上儲存二進位制日誌,最大程度的保證資料的不丟失
  • 使用 MySQL55的半同步複製,可以大大降低資料丟失的風險
  • 目前MHA支援一主多從架構,最少三臺服務,即一主兩從

二、MHA實驗

2.1 實驗目的

  • 通過MHA監控MySQL資料庫,在故障時自動進行切換,不影響業務
  • 當主庫失效時,備選主庫自動成為主庫

2.2 實驗拓撲圖

2.3.實驗思路

1) 安裝 MySQL 資料庫
2) 配置 MySQL 一主兩從
3) 安裝 MHA 軟體
4) 配置無密碼認證
5) 配置 MySQL MHA 高可用
6) 模擬 master 故障切換

2.3.1 安裝mysql

在三臺 MySQL 節點上分別安裝資料庫,MySQL 版本請使用 5.6.36,cmake 版本請使
用 2.8.6。之前部落格有詳細安裝mysql步驟,這邊不再說明。

2.3.2搭建mysql主從複製環境

  • 參考之前的部落格:

https://www.cnblogs.com/bushilengmo/p/13668756.html

  • 所有資料庫授權mha使用者對資料庫的操作許可權,每一個mysql資料庫都要設定
1 在所有資料庫節點上授權兩個使用者,一個是從庫同步使用,另外一個是 manager 使用。
2 mysql> grant replication slave on *.* to 'myslave'@'192.168.195.%' identified by '123';
3 mysql> grant all privileges on *.* to '
mha'@'192.168.195.%' identified by 'manager'; 4 mysql> flush privileges;

2.3.3在 Mysql1 主機上檢視二進位制檔案和同步點

mysql> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000001 |     1215 |              |                  |                   |
+-------------------+----------+--------------+------------------+-------------------+

2.3.4接下來在 Mysql2 和 Mysql3 分別執行同步。

mysql> change master to master_host='192.168.195.129',master_user='myslave',master_password='123',master_log_file='master-bin.000001',master_log_pos=1215; 
mysql> start slave;

2.3.5檢視 IO 和 SQL 執行緒都是 yes 代表同步是否正常。

mysql> show slave status\G;
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

必須設定兩個從庫為只讀模式:
mysql> set global read_only=1;

2.4所有節點安裝環境和Node元件和Manager元件

  • 所有伺服器上都要安裝mha依賴的環境,此處僅展示mha_manager的安裝
[root@mha_manager ~]# yum install epel-release --nogpgcheck -y
[root@mha_manager ~]# yum install -y perl-DBD-MySQL \
perl-Config-Tiny \
perl-Log-Dispatch \
perl-Parallel-ForkManager \
perl-ExtUtils-CBuilder \
perl-ExtUtils-MakeMaker \
perl-CPAN
  • 所有伺服器都安裝安裝node元件,此處僅展示master伺服器的安裝
[root@master ~]# tar zxvf /mnt/shuju資料庫/mha/mha4mysql-node-0.57.tar.gz 
[root@master ~]# cd mha4mysql-node-0.57/
[root@master mha4mysql-node-0.57]# yum install perl-Module-Install -y
[root@master mha4mysql-node-0.57]# perl Makefile.PL 
==> Auto-install the 1 mandatory module(s) from CPAN? [y] y    '//輸入y'
[root@master mha4mysql-node-0.57]# make
[root@master mha4mysql-node-0.57]# make install
  • 僅mha_manager伺服器安裝manager元件
[root@mha_manager ~]# tar zxvf /mnt/shuju資料庫/mha/mha4mysql-manager-0.57.tar.gz 
[root@mha_manager ~]# cd mha4mysql-manager-0.57/
[root@mha_manager mha4mysql-manager-0.57]# perl Makefile.PL 
[root@mha_manager mha4mysql-manager-0.57]# make
[root@mha_manager mha4mysql-manager-0.57]# make install

2.5配置節點間SSH免互動登陸

  • mha_manager主機配置到所有資料庫節點的金鑰對驗證
[root@MHA-manager ~]# ssh-keygen -t rsa //一路按回車鍵
[root@MHA-manager ~]# ssh-copy-id 192.168.195.129
[root@MHA-manager ~]# ssh-copy-id 192.168.195.130
[root@MHA-manager ~]# ssh-copy-id 192.168.195.131
  • 在master上配置到資料庫節點slave1和slave2的免密驗證
[root@Mysql1 ~]# ssh-keygen -t rsa
[root@Mysql1 ~]# ssh-copy-id 192.168.195.130
[root@Mysql1 ~]# ssh-copy-id 192.168.195.131
  • 在slave1上配置到資料庫節點master和slave2的免密驗證
[root@Mysql2 ~]# ssh-keygen -t rsa
[root@Mysql2 ~]# ssh-copy-id 192.168.195.129
[root@Mysql2 ~]# ssh-copy-id 192.168.195.131
  • 在slave2上配置到資料庫節點master和slave1的免密驗證
[root@Mysql3 ~]# ssh-keygen -t rsa
[root@Mysql3 ~]# ssh-copy-id 192.168.195.129
[root@Mysql3 ~]# ssh-copy-id 192.168.195.130

2.6配置MHA-Manager元件

  • 在 manager 節點上覆制相關指令碼到/usr/local/bin 目錄
[root@mha_manager ~]# cp -ra /root/mha4mysql-manager-0.57/samples/scripts /usr/local/bin
[root@mha_manager samples]# ls -l /usr/local/bin/scripts/
-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_manager ~]# cp /usr/local/bin/scripts/master_ip_failover /usr/local/bin/    '//自動切換時 VIP管理的指令碼'
  • 修改master_ip_failover 指令碼
[root@mha_manager ~]# 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.195.200';
my $brdc = '192.168.195.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-manager ~]# mkdir /etc/masterha
[root@MHA-manager ~]# cp /root/mha4mysql-manager-0.57/samples/conf/app1.cnf /etc/masterha/
[root@MHA-manager ~]# vim /etc/masterha/app1.cnf
[server default]
manager_workdir=/var/log/masterha/app1.log               ##manager工作目錄
manager_log=/var/log/masterha/app1/manager.log            #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使用者的密碼,這個密碼是前文中建立監控使用者的那個密碼
user=mha        #設定監控使用者root
ping_interval=1      #設定監控主庫,傳送ping包的時間間隔,預設是3秒,嘗試三次沒有迴應的時候自動進行railover
remote_workdir=/tmp    #設定遠端mysql在發生切換時binlog的儲存位置
repl_password=123        #設定複製使用者的密碼
repl_user=myslave           #設定複製使用者的使用者
report_script=/usr/local/send_report      //設定發生切換後傳送的報警的指令碼
secondary_check_script=/usr/local/bin/masterha_secondary_check -s 192.168.195.130 -s 192.168.195.131
shutdown_script=""  #設定故障發生後關閉故障主機指令碼(該指令碼的主要作用是關閉主機放在發生腦裂,這裡沒有使用)
ssh_user=root      #設定ssh的登入使用者名稱

[server1]
hostname=192.168.195.129
port=3306

[server2]
hostname=192.168.195.130
port=3306
candidate_master=1    #//設定為候選master,如果設定該引數以後,發生主從切換以後將會將此從庫提升為主庫,即使這個主庫不是叢集中事件最新的slave
check_repl_delay=0    

[server3] hostname=192.168.195.131 port=3306

2.7測試 ssh 無密碼認證,如果正常最後會輸出 successfully,如下所示

[root@MHA-manager ~]# masterha_check_ssh -conf=/etc/masterha/app1.cnf

Tue Nov 26 23:09:45 2019 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Tue Nov 26 23:09:45 2019 - [info] Reading application default configuration from /etc/masterha/app1.cnf..
Tue Nov 26 23:09:45 2019 - [info] Reading server configuration from /etc/masterha/app1.cnf..
Tue Nov 26 23:09:45 2019 - [info] Starting SSH connection tests..
Tue Nov 26 23:09:46 2019 - [debug] 
Tue Nov 26 23:09:45 2019 - [debug]  Connecting via SSH from root@192.168.195.130(192.168.195.130:22) to root@192.168.195.131(192.168.195.131:22)..
Tue Nov 26 23:09:46 2019 - [debug]   ok.
Tue Nov 26 23:09:47 2019 - [debug] 
Tue Nov 26 23:09:46 2019 - [debug]  Connecting via SSH from root@192.168.195.131(192.168.195.131:22) to root@192.168.195.130(192.168.195.130:22)..
Tue Nov 26 23:09:47 2019 - [debug]   ok.
Tue Nov 26 23:09:47 2019 - [info] All SSH connection tests passed successfully.

2.8 啟動MHA

  • 第一次配置需要去master上手動開啟虛擬IP
[root@Mysql1 ~]# /sbin/ifconfig ens33:1 192.168.195.200/24
  • 啟動mha
[root@MHA-manager ~]# 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 &
[1] 129929

三、驗證實驗

1 [root@MHA-manager ~]#tailf /var/log/masterha/app1/manager.log     //啟用監控觀察日誌記錄
2 [root@Mysql1 ~]# pkill -9 mysql         //檢視master變化

3.1 故障模擬:

  • 在主庫上:pkill mysqld

可以看到從庫的狀態,其中之一肯定有切換到主庫的
切換備選主庫的演算法:
1.一般判斷從庫的是從(position/GTID)判斷優劣,資料有差異,最接近於master的slave,成為備選主。
2.資料一致的情況下,按照配置檔案順序,選擇備選主庫。
3.設定有權重(candidate_master=1),按照權重強制指定備選主。
1)預設情況下如果一個slave落後master 100M的relay logs的話,即使有權重,也會失效。
2)如果check_repl_delay=0的話,即使落後很多日誌,也強制選擇其為備選主。

3.2故障修復步驟:

  • 修復db
/etc/init.d/mysqld start

  • 修復主從
>change master to master_host='192.168.195.130',master_user='myslave',master_password='123',master_log_file='master-bin.000002',master_log_pos=154;
>start slave;

  • 修改配置檔案(再把這個記錄新增進去,因為它檢測掉失效時候會自動消失)
vi /etc/masterha/app1.cnf
[server1]
hostname=192.168.195.129
port=3306

  • 啟動manager(在manager那臺機器上)
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 &