MySQL高可用MHA

准备: 在主从复制的基础上面去做一主两从的GTID复制
server1:172.25.40.1(master,mha)
server2:172.25.40.2(slave)
server3:172.25.40.3(slave)

MHA所需安装包:

mha4mysql-manager-0.56-0.el6.noarch.rpm
mha4mysql-node-0.56-0.el6.noarch.rpm
perl-Config-Tiny-2.12-7.1.el6.noarch.rpm
perl-Email-Date-Format-1.002-5.el6.noarch.rpm
perl-Log-Dispatch-2.27-1.el6.noarch.rpm
perl-Mail-Sender-0.8.16-3.el6.noarch.rpm
perl-Mail-Sendmail-0.79-12.el6.noarch.rpm
perl-MIME-Lite-3.027-2.el6.noarch.rpm
perl-MIME-Types-1.28-2.el6.noarch.rpm
perl-Parallel-ForkManager-0.7.9-1.el6.noarch.rpm

【server2】【server3】下载安装包

yum install -y mha4mysql-node-0.56-0.el6.noarch.rpm 

【server1】

[root@server1 ~]# ssh-keygen ##mha分发公钥和密钥进行免密连接
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
[root@server1 ~]# ssh-copy-id 172.25.40.1
[root@server1 ~]# scp -r .ssh/ server2:
[root@server1 ~]# scp -r .ssh/ server3:

MySQL高可用MHA_第1张图片

[root@server1 ~]# mkdir -p /etc/masterha
[root@server1 ~]# cd /etc/masterha/
[root@server1 masterha]# vim app1.cnf
[server default]
manager_workdir=/etc/masterha    //设置manager的工作目录
manager_log=/etc/masterha/app1.log     //设置manager的日志
master_binlog_dir=/var/lib/mysql    //设置master 保存binlog的位置,以便MHA可以找到master的日志,我这里的也就是mysql的数据目录
#master_ip_failover_script= /usr/local/bin/master_ip_failover //设置自动failover时候的切换脚本
#master_ip_online_change_script= /usr/local/bin/master_ip_online_change //设置手动切换时候的切换脚本
password=Westos.123    //登陆mysql的密码
user=root        //设置监控用户root
ping_interval=1    //设置监控主库,发送ping包的时间间隔
remote_workdir=/tmp     //设置远端mysql在发生切换时binlog的保存位置
repl_password=Westos.123   //设置复制(slave)用户的密码
repl_user=linux          //设置复制环境中的复制用户名
#report_script=/usr/local/send_report //设置发生切换后发送的报警的脚本
#secondary_check_script= /usr/local/bin/masterha_secondary_check -s server03 -s server02
shutdown_script=""      //设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭
主机放在发生脑裂,这里没有使用)
ssh_user=root           //设置ssh的登录用户名

[server1]
hostname=172.25.40.1
port=3306

[server2]
hostname=172.25.40.2
port=3306
candidate_master=1   //设置为候选master,如果设置该参数以后,发生主从切换以后将>会将此从库提升为主库,即使这个主库不是集群中事件最新的slave
check_repl_delay=0   //默认情况下如果一个slave落后master 100M的relay logs的话,MHA将不会选择该slave作为一个新的master,因为对于这个slave的恢复需要花费很长时间,通过设置check_repl_delay=0,MHA触发切换在选择一个新的master的时候将会忽略复制延时,这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主在切换的过程中一定是新的master

[server3]
hostname=172.25.40.3
port=3306
[root@server1 ~]# masterha_check_ssh --conf=/etc/masterha/app1.cnf #检查MHA Manger到所有MHA Node的SSH连接状态

MySQL高可用MHA_第2张图片

[root@server1 ~]# mysql -p
mysql> grant all  on *.* to root@'172.25.40.%' identified by 'Westos.123';  #在master主机授权root
[root@server1 ~]# masterha_check_repl --conf=/etc/masterha/app1.cnf #查看整个集群的状态

MySQL高可用MHA_第3张图片
如果出现NOT OK!
报错为:read_only=1
解决:在server2和server3上
mysql> set GLOBAL read_only=1;

手动切换

将server1的master手动切换到server2上

[root@server1 ~]# masterha_master_switch --conf=/etc/masterha/app1.cnf --master_state=alive --new_master_host=172.25.40.2 --new_master_port=3306 --orig_master_is_new_slave     
[root@server1 ~]# mysql -p
mysql> show slave status\G;


测试:
【server2】创建数据库表

mysql> create database westos;
mysql> use westos;
mysql> create table userlist(
    -> username varchar(15) not null,
    -> password varchar(25) not null);
mysql> insert into userlist values ('user1','123');
mysql> insert into userlist values ('user2','123');
mysql> select * from userlist;

MySQL高可用MHA_第4张图片
【server3】

[root@server3 ~]# mysql -p
mysql> show slave status\G;

MySQL高可用MHA_第5张图片

mysql> show databases;
mysql> use westos;
mysql> select * from userlist;

MySQL高可用MHA_第6张图片
可以看到在server2上建立的用户信息也可以同步到server3上。

在每次切换master前在slave主机上执行下面操作:

mysql> set global read_only=1;

自动切换

【server1】 slave:

[root@server1 ~]# nohup masterha_manager --conf=/etc/masterha/app1.cnf  --ignore_last_failover  &     #进程打入后台

【server2】将master杀死,自动切换到server1,将server1设为master:

[root@server2 ~]# ps ax #可以看到进程
 3570 pts/0    S      0:00 /bin/sh /usr/bin/mysqld_safe --datadir=/var/lib/mysql --socket=/va
 3863 pts/0    Sl     0:00 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-
[root@server2 ~]# kill -9 3570
[root@server2 ~]# kill -9 3863

【server1】现在已经成为master:

[root@server1 ~]# mysql -p
mysql> grant replication slave on *.* to linux@'172.25.40.%' identified by 'Westos.123';    #授权
mysql> show master status;
mysql> use westos;
mysql> insert into westos.userlist values ('user3','333');
mysql> insert into westos.userlist values ('user4','444');

这里写图片描述
MySQL高可用MHA_第7张图片
【server3】查看信息:

[root@server2 ~]# mysql -p
mysql> stop slave;
mysql> reset slave;
mysql> reset master;
mysql> start slave;
mysql> show slave status\G;
mysql> use westos;
mysql> select * from userlist;

MySQL高可用MHA_第8张图片
MySQL高可用MHA_第9张图片
【server2】查看信息:

[root@server2 ~]# mysql -p
mysql> change master to master_host='172.25.40.1', master_user='linux', master_password='Westos.123', master_auto_position=1;    #连接master
mysql> start slave;
mysql> show slave status\G; 
mysql> use westos;
mysql> select * from userlist;

MySQL高可用MHA_第10张图片

[root@server1 ~]# vim /etc/masterha/app1.cnf 
  5 master_ip_failover_script= /usr/local/bin/master_ip_failover
  6 master_ip_online_change_script= /usr/local/bin/master_ip_online_change
[root@server1 ~]# vim master_ip_failover 
  1 #!/usr/bin/env perl
  2 use strict;
  3 use warnings FATAL => 'all';
  4 use Getopt::Long;
  5 
  6 my (
  7     $command,          $ssh_user,        $orig_master_host, $orig_master_ip,
  8     $orig_master_port, $new_master_host, $new_master_ip,    $new_master_port
  9 );
 10 
 11 my $vip = '172.25.40.100/24';
 12 my $ssh_start_vip = "/sbin/ip addr add $vip dev eth0";
 13 my $ssh_stop_vip = "/sbin/ip addr del $vip dev eth0";
 14 
 15 
 16 GetOptions(
 17     'command=s'          => \$command,
 18     'ssh_user=s'         => \$ssh_user,
 19     'orig_master_host=s' => \$orig_master_host,
 20     'orig_master_ip=s'   => \$orig_master_ip,
 21     'orig_master_port=i' => \$orig_master_port,
 22     'new_master_host=s'  => \$new_master_host,
 23     'new_master_ip=s'    => \$new_master_ip,
 24     'new_master_port=i'  => \$new_master_port,
 25 );
 26 
 27 exit &main();
 28 
 29 sub main {
 30 
 31     print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";
 32 
 33     if ( $command eq "stop" || $command eq "stopssh" ) {
 34 
 35         my $exit_code = 1;
 36         eval {
 37             print "Disabling the VIP on old master: $orig_master_host \n";
 38             &stop_vip();
 39             $exit_code = 0;
 40         };
 41         if ($@) {
 42             warn "Got Error: $@\n";
 43             exit $exit_code;
 44         }
 45         exit $exit_code;
 46     }
 47     elsif ( $command eq "start" ) {
 48 
 49         my $exit_code = 10;
 50         eval {
 51             print "Enabling the VIP - $vip on the new master - $new_master_host \n";
 52             &start_vip();
 53             $exit_code = 0;
 54         };
 55         if ($@) {
 56             warn $@;
 57             exit $exit_code;
 58         }
 59         exit $exit_code;
 60     }
 61     elsif ( $command eq "status" ) {
 62         print "Checking the Status of the script.. OK \n";
 63         exit 0;
 64     }
 65     else {
 66         &usage();
 67         exit 1;
 68     }
 69 }
 70 
 71 sub start_vip() {
 72     `ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
 73 }
 74 sub stop_vip() {
 75      return 0  unless  ($ssh_user);
 76     `ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
 77 }
 78 
 79 sub usage {
 80     print
 81     "Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --ori g_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_po rt=port\n";
 82 }
[root@server1 ~]# vim master_ip_online_change 
  1 #!/usr/bin/env perl
  2 use strict;
  3 use warnings FATAL =>'all';
  4 
  5 use Getopt::Long;
  6 
  7 my $vip = '172.25.40.100/24';
  8 my $ssh_start_vip = "/sbin/ip addr add $vip dev eth0";
  9 my $ssh_stop_vip = "/sbin/ip addr del $vip dev eth0";
 10 my $exit_code = 0;
 11 
 12 my (
 13   $command,              $orig_master_is_new_slave, $orig_master_host,
 14   $orig_master_ip,       $orig_master_port,         $orig_master_user,
 15   $orig_master_password, $orig_master_ssh_user,     $new_master_host,
 16   $new_master_ip,        $new_master_port,          $new_master_user,
 17   $new_master_password,  $new_master_ssh_user,
 18 );
 19 GetOptions(
 20   'command=s'                => \$command,
 21   'orig_master_is_new_slave' => \$orig_master_is_new_slave,
 22   'orig_master_host=s'       => \$orig_master_host,
 23   'orig_master_ip=s'         => \$orig_master_ip,
 24   'orig_master_port=i'       => \$orig_master_port,
 25   'orig_master_user=s'       => \$orig_master_user,
 26   'orig_master_password=s'   => \$orig_master_password,
 27   'orig_master_ssh_user=s'   => \$orig_master_ssh_user,
 28   'new_master_host=s'        => \$new_master_host,
 29   'new_master_ip=s'          => \$new_master_ip,
 30   'new_master_port=i'        => \$new_master_port,
 31   'new_master_user=s'        => \$new_master_user,
 32   'new_master_password=s'    => \$new_master_password,
 33   'new_master_ssh_user=s'    => \$new_master_ssh_user,
 34 );
 35 
 36 
 37 exit &main();
 38 
 39 sub main {
 40 
 41 #print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n"; 
 42 
 43 if ( $command eq "stop" || $command eq "stopssh" ) {
 44 
 45         # $orig_master_host, $orig_master_ip, $orig_master_port are passed. 
 46         # If you manage master ip address at global catalog database, 
 47         # invalidate orig_master_ip here. 
 48         my $exit_code = 1;
 49         eval {
 50             print "\n\n\n***************************************************************\n";
 51             print "Disabling the VIP - $vip on old master: $orig_master_host\n";
 52             print "***************************************************************\n\n\n\n";
 53 &stop_vip();
 54             $exit_code = 0;
 55         };
 56         if ($@) {
 57             warn "Got Error: $@\n";
 58             exit $exit_code;
 59         }
 60         exit $exit_code;
 61 }
 62 elsif ( $command eq "start" ) {
 63 
 64         # all arguments are passed. 
 65         # If you manage master ip address at global catalog database, 
 66         # activate new_master_ip here. 
 67         # You can also grant write access (create user, set read_only=0, etc) here. 
 68 my $exit_code = 10;
 69         eval {
 70             print "\n\n\n***************************************************************\n";
 71             print "Enabling the VIP - $vip on new master: $new_master_host \n";
 72             print "***************************************************************\n\n\n\n";
 73 &start_vip();
 74             $exit_code = 0;
 75         };
 76         if ($@) {
 77             warn $@;
 78             exit $exit_code;
 79         }
 80         exit $exit_code;
 81 }
 82 elsif ( $command eq "status" ) {
 83         print "Checking the Status of the script.. OK \n";
 84         `ssh $orig_master_ssh_user\@$orig_master_host \" $ssh_start_vip \"`;
 85         exit 0;
 86 }
 87 else {
 88 &usage();
 89         exit 1;
 90 }
 91 }
 92 
 93 # A simple system call that enable the VIP on the new master 
 94 sub start_vip() {
 95 `ssh $new_master_ssh_user\@$new_master_host \" $ssh_start_vip \"`;
 96 }
 97 # A simple system call that disable the VIP on the old_master 
 98 sub stop_vip() {
 99 `ssh $orig_master_ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
100 }
101 
102 sub usage {
103 print
104 "Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_ma ster_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=p ort\n";
105 }

【server1】此时为master主机:

[root@server1 ~]# ip addr add 172.25.40.100/24 dev eth0 #加入vip
[root@server1 ~]# mv master_ip_* /usr/local/bin
[root@server1 ~]# cd /usr/local/bin
[root@server1 bin]# chmod +x *
[root@server1 ~]# nohup masterha_manager --conf=/etc/masterha/app1.cnf --ignore_last_failover & #将进程打入后台

连接vip服务端,进行测试

[kiosk@foundation40 ~]$ ssh root@172.25.40.100
mysql> use westos
mysql> select * from userlist;    
mysql> insert into userlist values ('user5','555');   #添加信息

【server2】【server3】上查看建立的信息

mysql> use westos
mysql>  select * from userlist;

MySQL高可用MHA_第11张图片

【server1】结束数据库端,自动跳转其他master端

[root@server1 ~]# ps ax
 3553 pts/0    S      0:00 /bin/sh /usr/bin/mysqld_safe --datadir=/var/lib/mysql --socket=/var/lib/m
 3846 pts/0    Sl     0:13 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/m
[root@server1 ~]# kill -9 3553
[root@server1 ~]# kill -9 3846

【server2】 master切换到server2主机上
MySQL高可用MHA_第12张图片
查看server1的VIP已经漂移到server2的主机上,表示master已经切换到了server2主机上

【server1】将server1主机连接到master上

[root@server1 ~]# /etc/init.d/mysqld start
[root@server1 ~]# mysql -p
mysql> change master to master_host='172.25.40.2', master_user='linux', master_password='Westos.123', master_auto_position=1;
mysql> use westos;
mysql> select * from userlist;

MySQL高可用MHA_第13张图片

你可能感兴趣的:(MySQL高可用MHA)