MHA部署mysql資料庫的高可用
1、前期準備
1、架構圖

2、IP規劃
Manager: 192.168.226.123
MySQL主: 192.168.226.111
MySQL從1: 192.168.226.112
MySQL從2: 192.168.226.113
3、伺服器配置
檢視系統
cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
1核1G
2、安裝前檢查
1.網絡情況
ping www.baidu.com 檢測是否有網絡
2.IP位址
Ifconfig 檢視IP位址,與IP規劃位址保持一緻
3.防火牆
檢測防火牆是否關閉
systemctl status firewalld
沒關閉就先關閉防火牆
Systemctl stop firewalld
4.Selinux
enforcing 執行SELinux安全政策
permissive SELinux列印警告而不是強制執行(警告模式)
disabled 沒有加載SELinux政策
檢測selinux
getenforce
沒關閉的話關閉
關閉selinux
vim /etc/selinux/config
SELINUX=disabled
5.系統保持一緻
uname -r
6.時間同步
時間必須要同步,否則後面做的時候會報錯
date #檢視系統時間
時間不同步
yum -y install ntpdate #安裝時間同步工具
ntpdate pool.ntp.org #同步時間
安裝epel源:
先安裝wget用來從網絡上下載下傳軟體包
yum -y install wget
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
MHA manager源碼包:
mha4mysql-manager-0.57.tar.gz
MHA node源碼包:
mha4mysql-node-0.57.tar.gz
3、安裝部署
1、配置免密
互相配置免密
ssh-keygen 生成秘鑰對
ssh-copy-id [email protected] 發送公鑰
2、配置mysql主從
1、安裝mysql
yum -y install mariadb-server mariadb
2、修改配置檔案
mysql主:(192.168.226.111)
vim /etc/my.cnf
#必須寫在[mysqld]子產品下
server-id=1
log-bin=mysql-bin
Mysql從1:(192.168.226.112)
vim /etc/my.cnf
#id不能一樣
server-id=2
log-bin=slave-bin
relay-log=slave-log
mysql從2:(192.168.226.113)
vim /etc/my.cnf
#id不能一樣
server-id=3
log-bin=slave2-bin
relay-log=slave2-log
3、開啟并進入MySQL
systemctl start mariadb
mysql
4、授權從的複制權限(192.168.226.111)
grant replication slave on *.* to [email protected]'%' identified by '123';
flush privileges;
show master status;
5、從(192.168.226.112/192.168.226.113)
stop salve;
change master to master_host='192.168.226.111', master_user='slave', master_password='123', master_log_file='mysql-bin.000003', master_log_pos=533;
start slave;
show slave status\G;
雙yes即為成功
6、從設定為隻讀模式(192.168.226.112/192.168.226.113)
set global read_only=1;
7、授權manager檢測mysql權限(三台mysql都做)
grant all on *.* to [email protected]'192.168.226.%' identified by '123';
8、關閉資料庫relaylog自動删除
set global relay_log_purge = 0;
3、安裝node節點(所有主機都安裝)
1、安裝依賴
yum -y install perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker perl-DBD-MySQL perl-devel perl-CPAN
2、上傳node源碼包
3、/etc下建立mha目錄
mkdir /etc/mha
4、解壓源碼包并編譯安裝
tar xf mha4mysql-node-0.57.tar.gz
mv mha4mysql-node-0.57 /etc/mha/node
cd /etc/mha/node/
perl Makefile.PL && make && make install
4、安裝manager節點(192.168.226.123)
1、安裝依賴
yum -y install epel-release --nogpgcheck
yum -y install perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes
2、上傳manager源碼包
3、解壓并編譯安裝
tar xf mha4mysql-manager-0.57.tar.gz
mv mha4mysql-manager-0.57 /etc/mha/manager
cd /etc/mha/manager/
perl Makefile.PL && make && make install
4、修改配置檔案
[server default]
#設定manager的工作目錄
manager_workdir=/etc/mha/app1
#設定manager的日志
manager_log=/etc/mha/app1/manager.log
#設定master 儲存binlog的位置,以便MHA可以找到master的日志,我這裡的也就是mysql的資料目錄
master_binlog_dir="/var/lib/mysql"
#設定遠端mysql在發生切換時binlog的儲存位置
remote_workdir=/etc/mha/app1
#設定自動failover時候的切換腳本
master_ip_failover_script=/etc/mha/master_ip_failover
#設定手動切換時候的切換腳本
master_ip_online_change_script=/etc/mha/master_ip_online_change
#設定發生切換後發送的報警的腳本
report_script=/etc/mha/send_report
#設定監控使用者manager
user=manager
#設定mysql中root使用者的密碼,這個密碼是前文中建立監控使用者的那個密碼
password=123
#設定主從複制環境中使用者名
repl_user=manager
#設定主從複制使用者的密碼
repl_password=123
#設定監控主庫,發送ping包的時間間隔,嘗試四次沒有回應的時候自動進行failover
ping_interval=1
#一旦MHA到server02的監控之間出現問題,MHA Manager将會嘗試從server03登入到server02
secondary_check_script= masterha_secondary_check -s 192.168.226.112 -s 192.168.226.113
[server1]
hostname=192.168.226.111
port=3306
ssh_port=22
[server2]
hostname=192.168.226.112
port=3306
ssh_port=22
#設定為候選master,如果設定該參數以後,發生主從切換以後将會将此從庫提升為主庫,即使這個主庫不是叢集中事件最新的slave
candidate_master=1
#預設情況下如果一個slave落後master 100M的relay logs的話,MHA将不會選擇該slave作為一個新的master, 因為對于這個slave的恢複需要花費很長時間,通過設定check_repl_delay=0,MHA觸發切換 在選擇一個新的master的時候将會忽略複制延時,這個參數對于設定了candidate_master=1 的主機非常有用,因為這個候選主在切換的過程中一定是新的master
check_repl_delay=0
[server3]
hostname=192.168.226.113
port=3306
no_master=1
ssh_port=22
5、腳本(所有資料庫)
1、定時删除relaylog檔案
1、給relay-log建立目錄并做硬連接配接
mkdir -p /var/lib/mysql/logs1
ln /var/lib/mysql/relay-log* /var/lib/mysql/logs1/
2、編寫腳本
vim /etc/mha/purge_relay_log.sh
#!/bin/bash
user=root
#passwd=123 資料庫密碼,預設是沒有密碼的,是以注釋掉
port=3306
log_dir=’/var/lib/mysql/’
work_dir=’/var/lib/mysql/logs1’
purge=’/usr/local/bin/purge_relay_logs’
if [ ! -d $log_dir ]
then
mkdir $log_dir -p
fi
$purge --user=$user --password=$passwd --disable_relay_log_purge --port= $port --host=localhost --workdir=$work_dir >> $log_dir/purge_relay_logs.log 2>&1
3、測試
purge_relay_logs --user=root --host=localhost --port=3306 -disable_relay_log_purge --workdir=/var/lib/mysql/
最後結果出現 succeeded 即為成功
4、做定時任務定時删除
crontab -e
0 0 */3 * * sh purge_relay_log.sh
2、自動切換腳本
vim /etc/mha/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.181.111/24';
my $key = '0';
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 ([email protected]) {
warn "Got Error: [email protected]\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 ([email protected]) {
warn [email protected];
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";
}
3、手動切換腳本
vim /etc/mha/master_ip_online_change
#!/usr/bin/env perl
#手動切換
use strict;
use warnings FATAL =>'all';
use Getopt::Long;
my $vip = '192.168.181.111/24'; # Virtual IP
my $key = "0";
my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig ens33:$key down";
my $exit_code = 0;
my (
$command, $orig_master_is_new_slave, $orig_master_host,
$orig_master_ip, $orig_master_port, $orig_master_user,
$orig_master_password, $orig_master_ssh_user, $new_master_host,
$new_master_ip, $new_master_port, $new_master_user,
$new_master_password, $new_master_ssh_user,
);
GetOptions(
'command=s' => \$command,
'orig_master_is_new_slave' => \$orig_master_is_new_slave,
'orig_master_host=s' => \$orig_master_host,
'orig_master_ip=s' => \$orig_master_ip,
'orig_master_port=i' => \$orig_master_port,
'orig_master_user=s' => \$orig_master_user,
'orig_master_password=s' => \$orig_master_password,
'orig_master_ssh_user=s' => \$orig_master_ssh_user,
'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_user=s' => \$new_master_ssh_user,
);
exit &main();
sub main {
#print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";
if ( $command eq "stop" || $command eq "stopssh" ) {
# $orig_master_host, $orig_master_ip, $orig_master_port are passed.
# If you manage master ip address at global catalog database,
# invalidate orig_master_ip here.
my $exit_code = 1;
eval {
print "\n\n\n***************************************************************\n";
print "Disabling the VIP - $vip on old master: $orig_master_host\n";
print "***************************************************************\n\n\n\n";
&stop_vip();
$exit_code = 0;
};
if ([email protected]) {
warn "Got Error: [email protected]\n";
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "start" ) {
# all arguments are passed.
# If you manage master ip address at global catalog database,
# activate new_master_ip here.
# You can also grant write access (create user, set read_only=0, etc) here.
my $exit_code = 10;
eval {
print "\n\n\n***************************************************************\n";
print "Enabling the VIP - $vip on new master: $new_master_host \n";
print "***************************************************************\n\n\n\n";
&start_vip();
$exit_code = 0;
};
if ([email protected]) {
warn [email protected];
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {
print "Checking the Status of the script.. OK \n";
`ssh $orig_master_ssh_user\@$orig_master_host \" $ssh_start_vip \"`;
exit 0;
}
else {
&usage();
exit 1;
}
}
# A simple system call that enable the VIP on the new master
sub start_vip() {
`ssh $new_master_ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
# A simple system call that disable the VIP on the old_master
sub stop_vip() {
`ssh $orig_master_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";
}
4、郵件報警腳本
vim /etc/mha/send_report
#!/usr/bin/perl
#郵件報警
use strict;
use warnings FATAL => 'all';
use Mail::Sender;
use Getopt::Long;
#new_master_host and new_slave_hosts are set only when recovering master succeeded
my ( $dead_master_host, $new_master_host, $new_slave_hosts, $subject, $body );
my $smtp='smtp.qq.com'; #使用的郵箱
my $mail_from='[email protected]'; #發送的郵箱位址
my $mail_user='[email protected]'; #發送的使用者(郵箱位址)
my $mail_pass='xxxxxxxxxx'; #郵箱的秘鑰
my $mail_to=['[email protected]']; #要發送的的郵箱位址
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,
);
mailToContacts($smtp,$mail_from,$mail_user,$mail_pass,$mail_to,$subject,$body);
sub mailToContacts {
my ( $smtp, $mail_from, $user, $passwd, $mail_to, $subject, $msg ) = @_;
open my $DEBUG, "> /tmp/monitormail.log"
or die "Can't open the debug file:$!\n";
my $sender = new Mail::Sender {
ctype => 'text/plain; charset=utf-8',
encoding => 'utf-8',
smtp => $smtp,
from => $mail_from,
auth => 'LOGIN',
TLS_allowed => '0',
authid => $user,
authpwd => $passwd,
to => $mail_to,
subject => $subject,
debug => $DEBUG
};
$sender->MailMsg(
{
msg => $msg,
debug => $DEBUG
}
)
or print $Mail::Sender::Error;
return 1;
}
# Do whatever you want here
exit 0;
5、給腳本添加執行權限
chmod +x /etc/mha/master_ip_* send_report purge_relay_log.sh
6、manager檢測、啟動(192.168.226.123)
1、ssh免密檢測
/etc/mha/manager/bin/masterha_check_ssh --conf=/etc/mha/app1.cnf
出現 successfully 為成功
2、mysql主從狀态檢測
/etc/mha/manager/bin/masterha_check_repl --conf=/etc/mha/app1.cnf
下面這樣為檢測正常
3、給主資料庫添加VIP
ifconfig ens33:0 192.168.226.200 netmask 255.255.255.0
檢視是否生成VIP
4、啟動manager
nohup /etc/mha/manager/bin/masterha_manager --conf=/etc/mha/app1.cnf --ignore_last_failover >/tmp/mha_manager.log < /dev/null 2>&1 &
5、檢視主的狀态
/etc/mha/manager/bin/masterha_check_status --conf=/etc/mha/app1.cnf
4、測試
1、關閉主上的mariadb
systemctl stop mariadb
2、檢視主上vip是否消失
3、檢視從1(192.168.226.112)上出現IP,即 vip 漂移成功
192.168.226.112成為新主,然後啟動舊主192.168.226.111,然後為111和112做主從(112為主,111為從)
4、修改管理機(192.168.226.123)的manager配置檔案
vim /etc/mha/app1.cnf
5、啟動manager
nohup /etc/mha/manager/bin/masterha_manager --conf=/etc/mha/app1.cnf --ignore_last_failover >/tmp/mha_manager.log < /dev/null 2>&1 &
6、檢視狀态,此時192.168.226.112為主
/etc/mha/manager/bin/masterha_check_status --conf=/etc/mha/app1.cnf