MHA的搭建步骤

  • A+
所属分类:运维教程

Master High Availability又称MHA,是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的软件。MySQL故障切换过程中,MHA能够做到在30秒之内自动完成数据库的故障切换操作,并在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。

主机及实例IP

  1. Manager : 192.168.18.250
  2. Master : 172.16.18.2:3306
  3. Slave1 : 172.16.18.3:3306
  4. Slave2 : 172.16.18.4:3306
  5. VIP : 172.16.18.5

Slave的配置参数

  1. log_bin=/home/birdteam/log/mysql-bin
  2. read_only=1
  3. relay_log_purge=0
  4. #一主一从不用此项,两从及以上建议打开此参数,防止切换为成主库的从库自动删除中继日志后,无法给其他从库应用这部分日志

配置主从同步

  1. mysql>grant replication slave on *.* to 'repl_17zuoye'@'%' identified by 'office.repl.17zuoye';
  2. mysql>flush privileges;
  3. #三个节点都要配置,用于当某个slave升为主后其他的从进行同步
  4. mysql>change master to master_host='172.16.18.2',master_user='dtstack',master_port=3306,master_password='abc123',master_log_file='logbin.000014',master_log_pos=70980879;
  5. mysql>start slave;

配置SSH免秘钥,四台服务器之间可互通

  1. # ssh-keygen -t rsa
  2. # ssh-copy-id -i .ssh/id_rsa.pub root@172.16.18.2

四个节点安装EPEL源以及相关yum包

  1. # rpm -ivh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm          
  2. # yum -y install perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perlTime-HiRes

下载安装mha包

  1. # wget https://code.google.com/p/mysql-master-ha/wiki/Downloads?tm=2          
  2. manager节点:
  3. # rpm –ivh mha4mysql-manager-0.56-0.el6.noarch.rpm
  4. # rpm –ivh mha4mysql-node-0.56-0.el6.noarch.rpm
  5. node 节点:
  6. # rpm –ivh mha4mysql-node-0.56-0.el6.noarch.rpm

建立与授权mha用户

  1. mysql>GRANT ALL PRIVILEGES ON *.* TO 'mha'@'%' IDENTIFIED BY 'mhamha';
  2. mysql>flush privileges;

manager节点建立相关目录和配置文件

  1. # tree /mha
  2. /mha
  3. ├── app1
  4. │   ├── app1.conf
  5. │   └── manager.log
  6. └── conf
  7. ├── master_ip_failover_3306
  8. ├── master_ip_online_change
  9. └── send_report
  10. 2 directories, 5 files

相关配置文件内容

  1. # cat app1.conf
  2. [server default]
  3. manager_workdir = /mha/app1
  4. manager_log = /mha/app1/manager.log
  5. remote_workdir = /mha/app1
  6. master_ip_failover_script=/mha/conf/master_ip_failover_3306
  7. #master failover时执行
  8. report_script=/mha/conf/send_report
  9. #master failover时执行,发送邮件使用
  10. master_ip_online_change_script=/mha/conf/master_ip_online_change
  11. #master_switchover时执行(手动切换)
  12. user=mha
  13. password=mhamha
  14. ping_interval=1
  15. ping_type=CONNECT
  16. repl_password=office.repl.17zuoye
  17. repl_user=repl_17zuoye
  18. ssh_port=22
  19. ssh_user=root
  20. [server1]
  21. hostname = 10.200.3.2
  22. port=3306
  23. master_binlog_dir = /database1/data_5.6.17_3306/binlog
  24. candidate_master = 1
  25. #这个服务器有较高的优先级提升为新的master(还要具备:开启binlog使复制没有延迟)
  26. [server2]
  27. hostname = 10.200.3.3
  28. port=3306
  29. master_binlog_dir = /database1/data_5.6.17_3306/binlog
  30. candidate_master =1
  31. ignore_fail=1
  32. [server3]
  33. hostname = 10.200.3.4
  34. port=3306
  35. master_binlog_dir = /database1/data_5.6.17_3306/binlog
  36. candidate_master =1
  37. ignore_fail=1
  38. #如slave存在故障,在主库出现问题时默认情况下mha不会进行故障切换,该参数即设定MHA会在所有的机器有问题的时间也会进行故障切换
  39. no_master=1
  40. #不将这台主机转换为master

主库启动一个虚IP

  1. # /sbin/ifconfig em1:0 10.200.3.5/23 up

失败切换脚本

  1. # cat master_ip_failover_3306
  2. #!/usr/bin/env perl
  3. use strict;
  4. use warnings FATAL => 'all';
  5. use Getopt::Long;
  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. my $vip = '10.200.3.5/23';  # Virtual IP
  11. my $key = "0";
  12. my $ssh_start_vip = "/sbin/ifconfig em1:$key $vip";
  13. my $start_new_master_vip = "/sbin/ifconfig em1:$key $vip";
  14. my $ssh_stop_vip = "/sbin/ifconfig em1:$key down";
  15. my $arp = "/usr/sbin/arping -A -q -c 2 -I em1:$key 10.200.3.5";
  16. #虚IP配置,在哪个网卡上,key编号的对应
  17. GetOptions(
  18.     'command=s'          => \$command,
  19.     'ssh_user=s'         => \$ssh_user,
  20.     'orig_master_host=s' => \$orig_master_host,
  21.     'orig_master_ip=s'   => \$orig_master_ip,
  22.     'orig_master_port=i' => \$orig_master_port,
  23.     'new_master_host=s'  => \$new_master_host,
  24.     'new_master_ip=s'    => \$new_master_ip,
  25.     'new_master_port=i'  => \$new_master_port,
  26. );
  27. exit &main();
  28. sub main {
  29.     print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$start_new_master_vip===\n\n";
  30.     if ( $command eq "stop" || $command eq "stopssh" ) {
  31.         # $orig_master_host, $orig_master_ip, $orig_master_port are passed.
  32.         # If you manage master ip address at global catalog database,
  33.         # invalidate orig_master_ip here.
  34.         my $exit_code = 1;
  35.         eval {
  36.             print "Disabling the VIP on old master: $orig_master_host \n";
  37.             &stop_vip();
  38.             $exit_code = 0;
  39.         };
  40.         if ($@) {
  41.             warn "Got Error: $@\n";
  42.             exit $exit_code;
  43.         }
  44.         exit $exit_code;
  45.     }
  46.     elsif ( $command eq "start" ) {
  47.         # all arguments are passed.
  48.         # If you manage master ip address at global catalog database,
  49.         # activate new_master_ip here.
  50.         # You can also grant write access (create user, set read_only=0, etc) here.
  51.         my $exit_code = 10;
  52.         eval {
  53.             print "Enabling the VIP - $vip on the new master - $new_master_host \n";
  54.             &start_vip();
  55.             $exit_code = 0;
  56.         };
  57.         if ($@) {
  58.             warn $@;
  59.             exit $exit_code;
  60.         }
  61.         exit $exit_code;
  62.     }
  63.     elsif ( $command eq "status" ) {
  64.        # print "Checking the Status of the script.. OK \n";
  65.        # `ssh $ssh_user\@tm01.okooo.cn \" $ssh_start_vip \"`;
  66.         exit 0;
  67.     }
  68.     else {
  69.         &usage();
  70.         exit 1;
  71.     }
  72. }
  73. # A simple system call that enable the VIP on the new master
  74. sub start_vip() {
  75.     `ssh root\@$new_master_host \" $ssh_start_vip \"`;
  76.     `ssh root\@$new_master_host \" $arp \"`;
  77. }
  78. # A simple system call that disable the VIP on the old_master
  79. sub stop_vip() {
  80.     return 0 unless ($ssh_user);
  81.     `ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
  82. }
  83. sub usage {
  84.     print
  85.     "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";
  86. }

手动在线切换脚本

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

failover后发送邮件脚本

  1. # cat send_report
  2. #!/bin/bash
  3. source /root/.bash_profile
  4. orig_master_host=`echo "$1" | awk -F = '{print $2}'`
  5. new_master_host=`echo "$2" | awk -F = '{print $2}'`
  6. new_slave_hosts=`echo "$3" | awk -F = '{print $2}'`
  7. subject=`echo "$4" | awk -F = '{print $2}'`
  8. body=`echo "$5" | awk -F = '{print $2}'`
  9. #判断日志结尾是否有successfully,有则表示切换成功,成功与否都发邮件
  10. tac /mha/app1/manager.log | sed -n 2p | grep 'successfully' > /dev/null
  11. if [ $? -eq 0 ]
  12.   then
  13.   echo -e "MHA $subject 主从切换成功\n master:$orig_master_host --> $new_master_host \n $body \n 当前从库:$new_slave_hosts" | mailx -s "MySQL实例宕掉,MHA $subject 切换成功" noreply@birdteam.net
  14. else
  15.   echo -e "MHA $subject 主从切换失败\n master:$orig_master_host --> $new_master_host \n $body" | mailx -s "MySQL实例宕掉,MHA $subject 切换失败" noreply@birdteam.net
  16. fi

修改脚本属主属组,并且增加执行权限

  1. # chown mysql.mysql ./*
  2. # chmod +x ./*

检查SSH的配置

  1. # masterha_check_ssh --conf=/mha/app1/app1.conf
  2. Tue Jan  5 17:16:41 2016 - [info] All SSH connectiontests passed successfully.

检查MHA的配置

  1. # masterha_check_repl --conf=/mha/app1/app1.conf
  2. MySQL Replication Health is OK.

启动MHA的服务

  1. # masterha_manager --conf=/mha/app1/app1.conf

发生failover主从切换后,MHAmanager服务会自动停掉,且在manager_workdir目录下面生成文件app1.failover.complete,若想要启动MHA,必须先确保没有此文件

  1. # ll
  2. total 80
  3. -rw-r--r-- 1 mysql mysql   556 Aug 29 11:23 app1.conf
  4. -rw-r--r-- 1 root  root      0 Aug 29 15:33 app1.failover.complete
  5. -rw-r--r-- 1 root  root  69838 Aug 29 15:33 manager.log
  6. -rw-r--r-- 1 root  root    143 Aug 29 15:33 saved_master_binlog_from_192.168.100.111_3306_20160829153340.binlog

在线手动切换主从,如果MHA在运行,需要先停止MHA,然后再检查MHA当前设置

  1. # masterha_check_repl --conf=/mha/app1/app1.conf

手动切换

  • 如果不指定new_master_host,则会根据配置文件app1.cnf选出new_master_host,但new_master_port默认是3306
  1. masterha_master_switch --master_state=alive --conf=/mha/app1/app1.conf  --orig_master_is_new_slave -running_updates_limit=3600 --interactive=0
  • 以下为切换时指定了new_master_host和new_master_port
  1. masterha_master_switch --master_state=alive --conf=/mha/app1/app1.conf  --orig_master_is_new_slave -running_updates_limit=3600 --interactive=0 --new_master_host=10.200.3.2 --new_master_port=3306
  1. 参数--running_updates_limit如果现在master执行写操作的执行时间大于这个参数,或任何一台slave的Seconds_Behind_Master大于这个参数,那么master switch将自动放弃,默认参数为1s;
  2. 参数--interactive=0非交互切换,建议加上,可以大大加快切换速度,加上后库不忙时大概3秒内切换完成。

注意

  • 如果需要将现有的从库修改为从,再启动mha的时候可能会报错;
  1. Wed Sep  7 12:18:56 2016 - [error][/usr/share/perl5/vendor_perl/MHA/ServerManager.pm, ln671] Master 192.168.100.111:3306 from which slave 10.200.3.2(10.200.3.2:3306) replicates is not defined in the configuration file!
  • 切换脚本可在MHA的官网查看。
  • 我的微博
  • 这是微博的扫一扫
  • weinxin
  • 微信公众
  • 微信公众号扫一扫
  • weinxin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

目前评论:4   其中:访客  2   博主  2

    • avatar 萝卜树上 6

      签到成功!签到时间:今日的‎19‎:‎51‎:‎19,每日打卡,生活更精彩哦!

      • avatar PPT文档 3

        写的很精彩很全面 不错

        • avatar Penn Admin

          签到成功!签到时间:今日的下午7:37:08,每日打卡,生活更精彩哦!