理論+實驗:MHA高可用配置及故障切換(實驗超詳細版)
目錄
一、案例概述
1.1 案例概述
■ 傳統的mysql主從架構存在的問題
- 單點故障
◆目前MySQL已經成為市場上主流資料庫之一,考慮到業務的重要性,MySQL 資料庫單點問題已成為企業網站架構中最大的隱患。隨著技術的發展,MHA 的出現就是解決MySQL單點的問題。另外隨著企業資料量越來越龐大,資料庫的壓力又成為企業的另一個瓶頸,MySQL多主多從架構的出現可以減輕MySQL本身的壓力。本章將主要介紹 MHA的搭建和模擬 MySQL故障自動切換的過程。
1.2 案例前置知識點-1
■ MHA概述
- —套優秀的MySQL高可用環境下故障切換和主從複製的軟體
- MySQL故障過程中,MHA能做到0-30秒內自動完成故障切換
■ MHA的組成
- MHA Manager (管理節點)
- MHA Node (資料節點)
1.3 案例前置知識點-2
■ MHA特點
- 自動故障切換過程中,MHA試圖從宕機的主伺服器上儲存二進位制日誌,最大程度的保證資料不丟失
- 使用半同步複製,可以大大降低資料丟失的風險
- 目前MHA支援一主多從架構,最少三臺服務,即一主兩從
1.4 案例環境
■ 案例拓撲圖
二、案例實施
2.1 實驗思路
1、MHA架構
2、資料庫安裝
3、一主兩從
4、MHA搭建
2.2 案例環境
本案例環境
伺服器 CentOS7.6(64 位) MHA-manager/20.0.0.4
管理節點,安裝 manager 元件
伺服器 CentOS7.6(64 位) Mysql1/20.0.0.3 Master 節點,安裝 node 元件
伺服器 CentOS7.6(64 位) Mysql2/20.0.0.5 Slave 節點,安裝 node 元件
伺服器 CentOS7.6(64 位) Mysql3/20.0.0.6 Slave 節點,安裝 node 元件
這裡作業系統是 CentOS7 版本,所以這裡下載 MHA 版本是 0.57 版本。
2.3 案例環境案例需求
本案例要求通過 MHA 監控 MySQL 資料庫在故障時進行自動切換,不影響業務。
2.4 案例實現思路
1、 安裝 MySQL 資料庫
2、 配置 MySQL 一主兩從
3、 安裝 MHA 軟體
4、 配置無密碼認證
5、 配置 MySQL MHA 高可用
6、 模擬 master 故障切換
在三臺 MySQL 節點上分別安裝資料庫,MySQL 版本請使用 5.6.36,cmake 版本請使
用 2.8.6。下面只在 Mysql1 上面做演示,安裝過程如下。
#####所有伺服器最好都清除一下快取,重啟一下#####
[root@localhost ~]# iptables -F
[root@localhost ~]# setenforce 0
[root@localhost ~]# init 6
[root@mysql1 ~]# vim /etc/hosts ###對映一下,mysql1、mysql2、mysql3都要這麼做
20.0.0.3 mysql1
20.0.0.5 mysql2
20.0.0.6 mysql3
[root@mysql1 ~]# ping mysql3 ###ping一下就可以驗證是否對映成功
- 下面1-3步驟是mysql5.6的安裝步驟,我用的mysql5.7版本,已經裝好了,直接從步驟四開始做了
- 也可以看我部落格:https://blog.csdn.net/weixin_44733021/article/details/108466141,部落格是5.7版本mysql安裝
1. 安裝編譯依賴的環境
[root@Mysql1 ~]# yum -y install ncurses-devel gcc-c++ perl-Module-Install
2. 安裝 gmake 編譯軟體
[root@Mysql1 ~]# tar zxvf cmake-2.8.6.tar.gz
[root@Mysql1 ~]# cd cmake-2.8.6
[root@Mysql1 cmake-2.8.6]# ./configure
[root@Mysql1 cmake-2.8.6]# gmake && gmake install
3. 安裝 MySQL 資料庫
[root@Mysql1 ~]# tar -zxvf mysql-5.6.36.tar.gz
[root@Mysql1 ~]# cd mysql-5.6.36
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_EXTRA_CHARSETS=all \
-DSYSCONFDIR=/etc
[root@Mysql1 mysql-5.6.36]# make && make install
[root@Mysql1 mysql-5.6.36]# cp support-files/my-default.cnf /etc/my.cnf
[root@Mysql1 mysql-5.6.36]# cp support-files/mysql.server /etc/rc.d/init.d/mysqld
[root@Mysql1 ~]# chmod +x /etc/rc.d/init.d/mysqld
[root@Mysql1 ~]# chkconfig --add mysqld
[root@Mysql1 ~]# echo "PATH=$PATH:/usr/local/mysql/bin" >> /etc/profile
[root@Mysql1 ~]# source /etc/profile
[root@Mysql1 ~]# groupadd mysql
[root@Mysql1 ~]# useradd -M -s /sbin/nologin mysql -g mysql
[root@Mysql1 ~]# chown -R mysql.mysql /usr/local/mysql
[root@Mysql1 ~]# mkdir -p /data/mysql
/usr/local/mysql/scripts/mysql_install_db \
--basedir=/usr/local/mysql \
--datadir=/usr/local/mysql/data \
--user=mysql
- 修改 Master 的主配置檔案/etc/my.cnf 檔案,三臺伺服器的 server-id 不能一樣
[root@Mysql1 ~]# vi /etc/my.cnf
#default-character-set=utf8 ###最上面的字符集也要一定註釋掉,不然健康檢查過不去
[mysqld]
server-id = 1 ###id千萬別一樣
log_bin = master-bin ###開啟二進位制日誌
log-slave-updates = true ###執行從伺服器進行同步
[root@mysql3 ~]# systemctl restart mysqld ###重啟服務
配置從伺服器1:
在/etc/my.cnf 中修改或者增加下面內容。
[root@Mysql2 ~]# vim /etc/my.cnf
#default-character-set=utf8 ###最上面的字符集也要一定註釋掉,不然健康檢查過不去
server-id = 2 ###id千萬別一樣
log_bin = master-bin ###開啟二進位制日誌
relay-log = relay-log-bin ###中繼日誌要開啟
relay-log-index = slave-relay-bin.index ###索引也要
[root@mysql3 ~]# systemctl restart mysqld ###重啟服務
配置從伺服器2:
在/etc/my.cnf 中修改或者增加下面內容。
[root@Mysql2 ~]# vim /etc/my.cnf
#default-character-set=utf8 ###最上面的字符集也要一定註釋掉,不然健康檢查過不去
server-id = 3 ###id千萬別一樣
log_bin = master-bin ###開啟二進位制日誌
relay-log = relay-log-bin ###中繼日誌要開啟
relay-log-index = slave-relay-bin.index ###索引也要
[root@mysql3 ~]# systemctl restart mysqld ###重啟服務
- Mysql1、Mysql2、Mysql3 分別做兩個軟連結
[root@Mysql1 ~]# ln -s /usr/local/mysql/bin/mysql /usr/sbin/
[root@Mysql1 ~]# ln -s /usr/local/mysql/bin/mysqlbinlog /usr/sbin/
- Mysql1、Mysql2、Mysql3 啟動 MySQL。
[root@Mysql1 ~]# /usr/local/mysql/bin/mysqld_safe --user=mysql &
- 配置 MySQL 一主兩從,三臺都要做
1. MySQL 主從配置相對比較簡單。需要注意的是授權。步驟如下:
在所有資料庫節點上授權兩個使用者,一個是從庫同步使用,另外一個是 manager 使用。
mysql> grant replication slave on *.* to 'myslave'@'20.0.0.%' identified by '123';
mysql> grant all privileges on *.* to 'mha'@'20.0.0.%' identified by 'manager';
mysql> flush privileges; ###重新整理
-----------------------------------------!!!!第二條我沒做!!!!--------------------------------------
2. 下面三條授權按理論是不用新增的,但是做案例實驗環境時候通過 MHA 檢查MySQL 主從有報錯,
報兩個從庫通過主機名連線不上主庫,所以所有資料庫加上下面的授權。
mysql> grant all privileges on *.* to 'mha'@'Mysql1' identified by 'manager';
mysql> grant all privileges on *.* to 'mha'@'Mysql2' identified by 'manager';
mysql> grant all privileges on *.* to 'mha'@'Mysql3' identified by 'manager';
----------------------------------------------------------------------------------------------------------
3. 在 Mysql1 主機上檢視二進位制檔案和同步點
mysql> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000001 | 885 | | | |
+-------------------+----------+--------------+------------------+-------------------+
4. 接下來在 Mysql2 和 Mysql3 分別執行同步。
mysql> change master to master_host='20.0.0.3',master_user='myslave',master_password='123',master_log_file='master-bin.000003',master_log_pos=306;
mysql> flush privileges; ###重新整理
mysql> start slave; ###啟動slave
5. 檢視 IO 和 SQL 執行緒都是 yes 代表同步是否正常。
mysql> show slave status\G; ###兩個執行緒都yes就行
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
注意:這個時候主從同步就建立好了
必須設定mysql2、mysql3從庫為只讀模式:
mysql> set global read_only=1;
mysql> flush privileges; ###重新整理一下
注意:設定完成直接驗證主從複製功能
-------------------------------------------------------安裝 MHA 軟體---------------------------------------------------------------------------
- 所有伺服器上都安裝 MHA 依賴的環境,首先安裝 epel 源(四臺都要裝!!!)
[root@MHA-manager ~]# yum install epel-release --nogpgcheck -y
yum install -y perl-DBD-MySQL \
perl-Config-Tiny \
perl-Log-Dispatch \
perl-Parallel-ForkManager \
perl-ExtUtils-CBuilder \
perl-ExtUtils-MakeMaker \
perl-CPAN
- MHA 軟體包對於每個作業系統版本不一樣,這裡 CentOS7.4 必須選擇 0.57 版本,
在<注意:所有伺服器>上必須先安裝 node 元件,最後在 MHA-manager 節點上安裝 manager 元件,
因為 manager 依賴 node 元件,下面都是在 Mysql1 上操作演示安裝 node 元件。
mysql1、mysql2、mysql3上傳node就行、MHA的要上傳node、manager兩個包
[root@Mysql1 ~]# tar zxvf mha4mysql-node-0.57.tar.gz
[root@Mysql1 ~]# cd mha4mysql-node-0.57
[root@Mysql1 mha4mysql-node-0.57]# perl Makefile.PL
[root@Mysql1 mha4mysql-node-0.57]# make
[root@Mysql1 mha4mysql-node-0.57]# make install
- 在 MHA-manager 上安裝 manager 元件(!注意:一定要先安裝node 元件才能安裝manager 元件)
[root@MHA-manager ~]# tar zxvf mha4mysql-manager-0.57.tar.gz
[root@MHA-manager ~]# cd mha4mysql-manager-0.57/
[root@MHA-manager mha4MHA-manager-0.57]# perl Makefile.PL
[root@MHA-manager mha4MHA-manager-0.57]# make
[root@MHA-manager mha4MHA-manager-0.57]# make install
manager 安裝後在/usr/local/bin 下面會生成幾個工具,主要包括以下幾個:
masterha_check_ssh 檢查 MHA 的 SSH 配置狀況
masterha_check_repl 檢查 MySQL 複製狀況
masterha_manger 啟動 manager的指令碼
masterha_check_status 檢測當前 MHA 執行狀態
masterha_master_monitor 檢測 master 是否宕機
masterha_master_switch 控制故障轉移(自動或者手動)
masterha_conf_host 新增或刪除配置的 server 資訊
masterha_stop 關閉manager
- node 安裝後也會在/usr/local/bin 下面會生成幾個指令碼(這些工具通常由 MHA
Manager 的指令碼觸發,無需人為操作)主要如下:
save_binary_logs 儲存和複製 master 的二進位制日誌
apply_diff_relay_logs 識別差異的中繼日誌事件並將其差異的事件應用於其他的 slave
filter_mysqlbinlog 去除不必要的 ROLLBACK 事件(MHA 已不再使用這個工具)
purge_relay_logs 清除中繼日誌(不會阻塞 SQL 執行緒)
- 配置無密碼認證
6. 在 manager 上配置到所有資料庫節點的無密碼認證
[root@MHA-manager ~]# ssh-keygen -t rsa //一路按回車鍵
[root@MHA-manager ~]# ssh-copy-id 20.0.0.3 ###yes 然後輸入密碼,密碼是root登入密碼
[root@MHA-manager ~]# ssh-copy-id 20.0.0.5
[root@MHA-manager ~]# ssh-copy-id 20.0.0.6
7. 在 Mysql1 上配置到資料庫節點Mysql2和Mysql3的無密碼認證
[root@Mysql1 ~]# ssh-keygen -t rsa
[root@Mysql1 ~]# ssh-copy-id 20.0.0.5
[root@Mysql1 ~]# ssh-copy-id 20.0.0.6
8. 在 Mysql2 上配置到資料庫節點Mysql1和Mysql3的無密碼認證
[root@Mysql2 ~]# ssh-keygen -t rsa
[root@Mysql2 ~]# ssh-copy-id 20.0.0.3
[root@Mysql2 ~]# ssh-copy-id 20.0.0.6
9. 在 Mysql3 上配置到資料庫節點Mysql1和Mysql2的無密碼認證
[root@Mysql3 ~]# ssh-keygen -t rsa
[root@Mysql3 ~]# ssh-copy-id 20.0.0.3
[root@Mysql3 ~]# ssh-copy-id 20.0.0.5
- 配置 MHA(在MHA伺服器上配置)
1. 在 manager 節點上覆制相關指令碼到/usr/local/bin 目錄。
[root@MHA-manager ~]# cp -ra /root/mha4mysql-manager-0.57/samples/scripts /usr/local/bin
//拷貝後會有四個執行檔案
[root@atlas ~]# ll /usr/local/bin/scripts/
總用量 32
-rwxr-xr-x 1 mysql mysql 3648 5 月 31 2015 master_ip_failover #自動切換時 VIP 管理的指令碼
-rwxr-xr-x 1 mysql mysql 9872 5 月 25 09:07 master_ip_online_change #線上切換時 vip 的管理
-rwxr-xr-x 1 mysql mysql 11867 5 月 31 2015 power_manager #故障發生後關閉主機的指令碼
-rwxr-xr-x 1 mysql mysql 1360 5 月 31 2015 send_report #因故障切換後傳送報警的指令碼
- 複製上述的自動切換時 VIP 管理的指令碼到/usr/local/bin 目錄,這裡使用指令碼管理 VIP,(在MHA伺服器上配置)
[root@MHA-manager ~]# cp /usr/local/bin/scripts/master_ip_failover /usr/local/bin
- 修改內容如下:(刪除原有內容,直接複製)(在MHA伺服器上配置)
裡面全是註釋掉的,需要用替換方法 去掉註釋符 % s/^#// ,%全文,s替換,^# 開頭的替換成空的
注意:但第一行需要把#加上!!!
[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 = '20.0.0.200';
my $brdc = '20.0.0.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";
}
#############################新增內容部分解釋#########################################
my $vip = '20.0.0.200'; ###這個是漂移地址,一定要和當前伺服器節點一個網段
my $brdc = '20.0.0.255'; ###廣播號,廣播號確定了結束地址
my $ifdev = 'ens33'; ###當前網絡卡名稱,有的是eta,需要根據情況更改
my $key = '1'; ###邏輯子介面編號
my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip"; ###用ens33做他的邏輯子介面的漂移地址
my $ssh_stop_vip = "/sbin/ifconfig ens33:$key down"; ###關閉
my