【實戰】mysql-MHA企業真實案例

淺談mysql-MHA

一、MHA簡介

MHAMaster High Availability)目前在MySQL高可用方面是一個相對成熟的解決方案,它由日本人youshimaton開發,是一套優秀的作爲MySQL高可用性環境下故障切換和主從提升的高可用軟件。在MySQL故障切換過程中,MHA能做到0~30秒之內自動完成數據庫的故障切換操作,並且在進行故障切換的過程中,MHA能最大程度上保證數據庫的一致性,以達到真正意義上的高可用。

MHA由兩部分組成:MHA Manager(管理節點)和MHA Node(數據節點)。MHA Manager可以獨立部署在一臺獨立的機器上管理多個Master-Slave集羣,也可以部署在一臺Slave上。Master出現故障時,它可以自動將最新數據的Slave提升爲新的Master,然後將所有其他的Slave重新指向新的Master。整個故障轉移過程對應用程序是完全透明的。

 

【基本原理】:

  從宕機崩潰的master保存二進制日誌事件(binlog events);

  識別含有最新更新的slave;

  應用差異的中繼日誌(relay log)到其他的slave;

  應用從master保存的二進制日誌事件(binlog events);

  提升一個slave爲新的master;

  使其他的slave連接新的master進行復制;

 

MHA軟件由兩部分組成,Manager工具包和Node工具包,具體的說明如下:

Manager工具包主要包括以下幾個工具:

masterha_check_ssh               檢查MHA的SSH配置狀況

masterha_check_repl              檢查MySQL複製狀況

masterha_manger                啓動MHA

masterha_check_status             檢測當前MHA運行狀態

masterha_master_monitor             檢測master是否宕機

masterha_master_switch            控制故障轉移(自動或者手動)

masterha_conf_host              添加或刪除配置的server信息

Node工具包主要包括以下幾個工具:

save_binary_logs                保存和複製master的二進制日誌

apply_diff_relay_logs             識別差異的中繼日誌事件

filter_mysqlbinlog               去除不必要的ROLLBACK事件

purge_relay_logs                清除中繼日誌

 

 二、公司需求

  不影響mysql性能(不開啓半同步)

  不增加mysql服務器(按原有集羣,一主三從)

  不使用keepalived(多臺切換)

  不影響讀寫分離功能

 

 

1.mysql架構

wKioL1hlz-DzIY7oAAEjzyvKZuc660.jpg-wh_50

1.1

【測試MHA】:

角色

IP地址

主機名

MHA  manger

172.16.1.53
mha03

MySQL  master

172.16.1.51
mha01

MySQL  slave1

172.16.1.52
mha02

MySQL  slave2

172.16.1.53
mha03

Atlas

51、52、53
三臺都裝

 

2.安裝mysql

所需安裝包:

  mysql-5.5.32-linux2.6-x86_64.tar.gz

[root@db01 ~]# cd /usr/local/src/

[root@db01 src]# rz -y                                                         #將安裝包上傳至/usr/local/src目錄下

[root@db01src]# tar xf mysql-5.5.32-linux2.6-x86_64.tar.gz  #解壓二進制包

[root@db01 src]# mv mysql-5.5.32-linux2.6-x86_64/application/mysql-5.5.32     #移動並改名

[root@db01 src]# ln -s /application/mysql-5.5.32//application/mysql                  #做軟連接

[root@db01 scripts]# useradd mysql -s/sbin/nologin -M                           #創建mysql用戶

[root@db01 src]# cd/application/mysql/scripts/                                        #進入mysql初始化目錄

[root@db01 scripts]# ./mysql_install_db--user=mysql --datadir=/application/mysql/data/--basedir=/application/mysql/                                                         #初始化mysql

[root@db01 scripts]# cd ../support-files/                                               #進入mysql功能文件目錄

[root@db01 support-files]# cp my-small.cnf/etc/my.cnf          #mysql的配置文件拷貝到/etc

[root@db01 support-files]# cp mysql.server/etc/init.d/mysqld   #mysql啓動文件拷貝到/etc

[root@db01support-files]# sed -i 's#/usr/local#/application#g'/etc/init.d/mysqld /application/mysql/bin/mysqld_safe                                                              #修改啓動文件

[root@db01 support-files]# exportPATH="/application/mysql/bin/:$PATH"                                                                                                                                    #mysql的命令放置系統中

[root@db01support-files]# echo "exportPATH="/application/mysql/bin/:$PATH"" >> /etc/profile                                                                                 #將以上命令寫入環境變量

[root@db01support-files]# source /etc/profile                         #刷新環境變量

[root@db01support-files]# /etc/init.d/mysqld start                 #啓動mysql

StartingMySQL.... SUCCESS                                                       #mysql啓動成功

[root@db01support-files]# mysql -uroot password faxuan    #mysql設置密碼

[root@db01support-files]# netstat -anltup|grep 3306           #檢查mysql端口

[root@db01support-files]# ps -ef|grep mysql                       #檢查mysql進程

至此,mysql就搭建完畢,其它幾臺也同樣

 

3.設置主從複製

  主庫和從庫都要開啓bin-log日誌

  所有的mysqlserver-id不同

  創建從庫複製權限的用戶

 

【主庫操作】:

[root@db01 tools]# vim /etc/my.cnf              #修改配置文件

server-id      = 1                                                            #主庫爲1 從庫必須大於1

[root@db02tools]# /etc/init.d/mysqld restart             #重啓mysql

[root@db01 support-files]# mysql -uroot-pfaxuan    #登錄數據庫

mysql> grant replication slave on *.* to slave@'172.16.1.%' identified by '123456';     #授權用戶

mysql> show master status;                                       #查看主庫bin-log

+---------------------------+-----------+---------------------+-------------------------+

| File            | Position | Binlog_Do_DB |Binlog_Ignore_DB |

+---------------------------+------------+---------------------+------------------------+

| mysql-bin.000004 |  257 |            |               |            #記住標顏色的兩個值

+----------------------------+-----------+--------------------+-------------------------+

 

【從庫操作】:

[root@db01 tools]# vim /etc/my.cnf                                    #修改配置文件

server-id      = 1     == 1改爲2                                           #主庫爲1 從庫必須大於1

[root@db02 tools]# /etc/init.d/mysqld restart                    #重啓mysql

[root@db02 tools]# mysql -uroot -pfaxuan                        #登錄數據庫

mysql> change master to                                                    #在從庫上設置主庫信息

    ->master_host='172.16.1.51',                                          #主庫IP

    ->master_user='slave',                                                    #授權用戶(在主庫上操作授權的用戶)

    ->master_password='123456',                                       #授權用戶的密碼

    ->master_log_file='mysql-bin.000004',                         #剛纔主庫記錄的File

-> master_log_pos=257;                                             #剛纔主庫記錄的Position

mysql> start slave;                                                            #開啓複製

mysql> show slave status\G                                             #查看複製狀態

 Slave_IO_Running: Yes

Slave_SQL_Running:Yes                                                    #主從複製成功

至此,主從複製完畢,其它幾臺也同樣

 

【從庫設置】:

[root@db02 tools]# mysql -uroot -pfaxuan   #登錄mysql

mysql> set global relay_log_purge = 0;                           #禁用自動刪除功能

mysql> set global read_only=1;                                       #從庫不可寫

[root@db02 tools]# vim /etc/my.cnf                               #編輯配置文件

               relay_log_purge = 0                                          #不自動刪除relay log

[root@db02 tools]# /etc/init.d/mysqld restart               #重啓mysql

 

4、安裝mysql MHA

所需安裝包:

  mha4mysql-node-0.56-0.el6.noarch.rpm

  mha4mysql-manager-0.56-0.el6.noarch.rpm

 

【所有節點】:

[root@db01 ~]# yum install perl-DBD-MySQL -y   #安裝依賴包

mha4mysql-node-0.56-0.el6.noarch.rpm上傳到/usr/local/src

[root@db01 src]# rpm -ivhmha4mysql-node-0.56-0.el6.noarch.rpm                    #安裝

[root@db01 src]# mysql -uroot -pfaxuan                                                              #登錄mysql

mysql> grant all privileges on *.* tomha@'172.16.1.%' identified by 'mha';        #添加管理賬號

 

[root@db01 src]# ln -s/application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog  #創建軟連接

[root@db01 src]# ln -s/application/mysql/bin/mysql /usr/bin/mysql                      #創建軟連接

 

【管理節點】:

[root@mha03tools]# wget -O/etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo                                                                                   #使用epel

[root@db03 src]# yum install -y perl-Config-Tinyepel-release perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes                                           #安裝依賴包

mha4mysql-manager-0.56-0.el6.noarch.rpm 包上傳到/usr/local/src

[root@db03 src]# rpm -ivhmha4mysql-manager-0.56-0.el6.noarch.rpm  #安裝

[root@db03 src]# mkdir -p /etc/mha                                #/etc下創建mha目錄

[root@db03 src]# mkdir -p /var/log/mha/app1               #創建日誌目錄

[root@db03 src]# vim /etc/mha/app1.cnf                        #編輯配置文件

[server default]

manager_log=/var/log/mha/app1/manager                    #管理日誌目錄

manager_workdir=/var/log/mha/app1                            #管理工作目錄

master_binlog_dir=/application/mysql/data                   #主庫bin-log日誌

user=mha                                                                         #上一步授權的用戶

password=mha                                                               #上一步授權的密碼

ping_interval=2

repl_password=123456                                                   #複製密碼(主從)

repl_user=slave                                                                #複製用戶(主從)

ssh_user=root                                                                   #ssh遠程連接用戶

 

[server1]                                                                           #第一個主機

hostname=172.16.1.51                                                   #IP

port=3306                                                                       #端口

 

[server2]

candidate_master=1                                                    #優先的新主人(切換主庫優先)

check_repl_delay=0                                                     #忽略複製延遲

hostname=172.16.1.52

port=3306

 

[server3]

hostname=172.16.1.53

port=3306

【配置文件詳解】:

[server default]

manager_workdir=/var/log/masterha/app1.log                   ##設置manager的工作目錄

manager_log=/var/log/masterha/app1/manager.log          ##設置manager的日誌

master_binlog_dir=/data/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=123456        ##設置mysqlroot用戶的密碼,這個密碼是前文中創建監控用戶的那個密碼

user=root              設置監控用戶root

ping_interval=1         ##設置監控主庫,發送ping包的時間間隔,默認是3秒,嘗試三次沒有迴應的時候自動進行railover

remote_workdir=/tmp    ##設置遠端mysql在發生切換時binlog的保存位置

repl_password=123456   ##設置複製用戶的密碼

repl_user=repl          ##設置複製環境中的複製用戶名

report_script=/usr/local/send_report    ##設置發生切換後發送的報警的腳本

secondary_check_script=/usr/local/bin/masterha_secondary_check -s server03 -s server02 --user=root--master_host=server02 --master_ip=192.168.0.50 --master_port=3306               ##一旦MHAserver02的監控之間出現問題,MHA Manager將會嘗試從server03登錄到server02

shutdown_script=""     ##設置故障發生後關閉故障主機腳本(該腳本的主要作用是關閉主機放在發生腦裂,這裏沒有使用)

ssh_user=root           ##設置ssh的登錄用戶名

 

[server1]

hostname=172.16.1.51

port=3306

 

[server2]

hostname=172.16.1.52

port=3306

candidate_master=1   ##設置爲候選master,如果設置該參數以後,發生主從切換以後將會將此從庫提升爲主庫,即使這個主庫不是集羣中事件最新的slave

check_repl_delay=0   ##默認情況下如果一個slave落後master 100Mrelay logs的話,MHA將不會選擇該slave作爲一個新的master,因爲對於這個slave的恢復需要花費很長時間,通過設置check_repl_delay=0,MHA觸發切換在選擇一個新的master的時候將會忽略複製延時,這個參數對於設置了candidate_master=1的主機非常有用,因爲這個候選主在切換的過程中一定是新的master

 

[server3]

hostname=172.16.1.53

port=3306

 

【配置ssh祕鑰登錄】:

[root@db01 src]# ssh-keygen -t rsa    #創建祕鑰對

[root@db01 src]# ssh-copy-id -i/root/.ssh/id_rsa.pub [email protected]    #分發公鑰,包括自己

[root@db01 src]# ssh-copy-id -i/root/.ssh/id_rsa.pub [email protected]

[root@db01 src]# ssh-copy-id -i/root/.ssh/id_rsa.pub [email protected]

其它兩臺也同樣配置

 

【測試】:

在管理機上操作

[root@db03 src]# masterha_check_ssh--conf=/etc/mha/app1.cnf   #測試ssh

Tue Aug 2 14:37:44 2016 - [info] All SSHconnection tests passed successfully. #說明ssh配置成功

[root@db03 src]# masterha_check_repl--conf=/etc/mha/app1.cnf                   #測試複製

MySQL Replication Health is OK.                                                                        #說明覆制配置成功

 

【啓動MHA】:

[root@db03 src]# nohup masterha_manager--conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover </dev/null > /var/log/mha/app1/manager.log 2>&1 &

 

【測試】:

[root@db02 src]# mysql -uroot -pfaxuan  #登錄從庫的mysql

mysql> show slave status\G                                                                         #查看複製狀態

wKioL1hl0a2CAtddAAAoh-khAXI099.png-wh_50

主庫是172.16.1.51

[root@db01 src]# /etc/init.d/mysqld stop #在主庫上執行,停掉主庫

mysql> show slave status\G  #再在從庫查看複製狀態

wKioL1hl0b2D9WcPAAAoc3tna-c635.png-wh_50

可以看到,主庫自動切換成了,mha配置文件中設置的172.16.1.53

 

再次啓動172.16.1.51主的mysql後,不會自動加入集羣。

需要手動修改配置文件,將172.16.1.51更改爲數據從庫。

本次MHA架構搭建成功。

三、測試VIP漂移

1.vip配置可以採用兩種方式:

  通過keepalived的方式管理虛擬ip的漂移。

  通過MHA自帶腳本方式啓動虛擬ip的方式(即不需要keepalived或者heartbeat類似的軟件)。

 

因爲公司的需求,這裏給大家介紹第二種方式:

 

2.修改配置文件:

[root@db03 bin]# vim /etc/mha/app1.cnf

[server default]

manager_log=/var/log/mha/app1/manager.log

manager_workdir=/var/log/mha/app1.log

master_binlog_dir=/application/mysql/data

master_ip_failover_script=/usr/local/bin/master_ip_failover        #MHA自帶腳本

password=mha

ping_interval=1

remote_workdir=/tmp

repl_password=123456

repl_user=slave

shutdown_script=""

ssh_user=root

user=mha

 

[server1]

hostname=172.16.1.51

port=3306

 

[server2]

hostname=172.16.1.52

port=3306

 

[server3]

hostname=172.16.1.53

port=3306

 

在這裏不配置之前介紹的以下兩個參數:

andidate_master=1                         #優先的新主人

heck_repl_delay=0                          #忽略複製延遲

因爲我們需要實現,多臺主機之間互相切換,不使用keepalived

這個配置比較適合兩臺服務器做半同步,然後再加上keepalived

 

3.編寫腳本:

#!/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 = '172.16.1.55/24';      #虛擬IP

my $key = '1';

my $ssh_start_vip = "/sbin/ifconfig eth1:$key$vip";

my $ssh_stop_vip = "/sbin/ifconfig eth1:$keydown";

 

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 ( $commandeq "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 \"`;

}

sub stop_vip() {

     return0  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";

}

[root@db01 ~]# ifconfig eth1:1 172.16.1.55     #手動給master上添加VIP

[root@db01 ~]#ip a|grep eth1

3: eth1:<BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen1000

    inet 172.16.1.51/24 brd 172.16.1.255 scopeglobal eth1

inet 172.16.1.55/16 brd172.16.255.255 scope global eth1:1

    #查看手動配置的VIP

 

4.測試:

wKioL1hl0jOz-w1vAAAhV26myqo241.png-wh_50


[root@db01 ~]# sysbench --test=oltp--oltp-table-size=1000000 --oltp-read-only=off --init-rng=on --num-threads=16--max-requests=0 --oltp-dist-type=uniform --max-time=1800 --mysql-user=root--mysql-socket=/tmp/mysql.sock --mysql-password=faxuan --db-driver=mysql--mysql-table-engine=innodb --oltp-test-mode=complex prepare

sysbench 0.4.12: multi-threaded system evaluation benchmark

 

Creating table 'sbtest'...

Creating 1000000 records in table 'sbtest'...  #插入100000萬條數據

mysql> stopslave; #在從庫52上執行,停止複製

[root@db01 ~]#/etc/init.d/mysqld stop #寫完數據後,將主庫進程停掉

wKioL1hl0kiz9fiCAAAdk7E5LSc801.png-wh_50

#VIP已經不在51上了

wKiom1hl0lrBKcMYAAA98NHAkHk112.png-wh_50

wKioL1hl0m6TkPrrAAAhNve4or8835.png-wh_50

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章