mysql HA方案: MHA

 

mysql-master-ha

mysql 作熱備和高可用的方法有不少種, 好比:php

mmm: http://mysql-mmm.org/html

mha: https://code.google.com/p/mysql-master-ha/node

heartbeat+brdb: http://lin128.blog.51cto.com/407924/279411 http://www.centos.bz/2012/03/achieve-drbd-high-availability-with-heartbeat/python

cluster(使用ndb引擎):http://database.51cto.com/art/201008/218326.htmmysql

雙master+keeplived: http://database.51cto.com/art/201012/237204.htmsql

雙master: http://yunnick.iteye.com/blog/1845301shell

這裏咱們不介紹其餘的方式以及優缺點,只介紹mha的安裝過程。數據庫

首先我這篇文檔參考了以下網頁:ubuntu

官方wiki: https://code.google.com/p/mysql-master-ha/wiki/Tutorialcentos

使用MHA作mysql的高可用:http://qiufengy.blog.51cto.com/391990/848468

Mysql5.5部署MHA: http://ylw6006.blog.51cto.com/470441/890360

mysql High Availability -MHA: http://www.vmcd.org/2012/04/mysql-high-availability-mha/

MySQL高可用性大殺器之MHA: http://huoding.com/2011/12/18/139

mysql-mha高可用 : http://blog.chinaunix.net/uid-28437434-id-3476641.html

另外有個slide講mha的,能夠看看:http://www.slideshare.net/ylouis83/mysqlmha

準備環境

官方文檔是用了4臺機器,因此我也用了4臺機器,分別是:

host1: 172.16.21.15 #manager, monitor ubuntu 13.04

host2: 172.16.21.23 #master ubuntu 12.04 server

hots3: 172.16.21.50 #備選master ubuntu 12.04 server

host4: 172.16.21.48 #slave ubuntu 12.04 server

mha本身不構建複製(replication)環境,因此它能夠重用之前的複製結構,關於mysql複製的拓撲結構能夠參考此文章:http://blog.csdn.net/hguisu/article/details/7325124

咱們這裏使用mysql半同步複製(semisync)架構, 半同步複製的介紹他搭建見此:http://hzcsky.blog.51cto.com/1560073/820859 http://haiker.iteye.com/blog/1632697

mysql半同步複製須要mysql版本5.5以上,另mysql 5.6之後開源協議有變, 推薦percona: http://www.percona.com/software/percona-server 或mariadb, 不過ubuntu中用apt-get 安裝軟件實在是很方便,我仍是使用apt-get install mysql-server-5.5 來安裝mysql的。

在host2, host3, host4 安裝mysql後,更改其/etc/mysql/my.cnf 添加以下內容:

server-id = 1 #不一樣的host server_id 必定要不同,我這裏host2爲1, host3 爲2, host4 爲3

log_bin = /var/log/mysql/mysql-bin.log #爲了安全,應該建立一個目錄存放binlog的,不過我很懶,就放到log目錄了,生產環境不能這樣

replicate_ignore_db = mysql

ps: 上面和下面全部的命令最好都使用root用戶執行,我曾經使用非 root用戶,最後發現很煩, 另ubuntu 默認root是不能夠ssh登錄的,要先:passwd root 給root添加密碼,這樣root就能夠ssh登錄了。

半同步複製開啓

master, host2上:

mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
mysql> set global rpl_semi_sync_master_enabled=1;
mysql> set global rpl_semi_sync_master_timeout=1000;
mysql> show global status like 'rpl%';

爲了讓mysql在重啓時自動加載該功能,在/etc/mysql/my.cnf 加入:

rpl_semi_sync_master_enabled=1

rpl_semi_sync_master_timeout=1000

備選master, host3 上:

mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
mysql> set global rpl_semi_sync_master_enabled=1;
mysql> set global rpl_semi_sync_master_timeout=1000;
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
mysql> set global rpl_semi_sync_slave_enabled=1;

在/etc/mysql/my.cnf中加入:

rpl_semi_sync_master_enabled=1 rpl_semi_sync_master_timeout=1000 rpl_semi_sync_slave_enabled=1

slave, host4 上:

mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
mysql> set global rpl_semi_sync_slave_enabled=1;

在/etc/mysql/my.cnf中加入:

rpl_semi_sync_slave_enabled=1

在備用節點和從節點的/etc/mysql/my.cnf中加入選項:

read_only=1 #這個設置待商榷,備選master設爲read only以後,master轉移到備選master後數據庫不可寫(有super權限的用戶仍是可寫)

relay_log_purge=0


在master上:

mysql> grant replication slave on *.* to repl@'172.16.21.%' identified by 'repl';
mysql> show master status;
記錄下 「File」和「Position」即當前主庫使用的二進制日誌名稱和位置。

在備選master和slave上:

mysql> change master to master_host="172.16.21.23",master_user="repl",master_password="repl",master_log_file="bin-log.000001",master_log_pos=255;

master_log_file 和 master_log_pos 是上面記下的東西。

在備選master上:

mysql> grant replication slave on *.* to repl@'172.16.21.%' identified by 'repl';

而後在備選master和slave上:

mysql>start slave;
mysql>show slave status\G;
# 若是 Slave_IO_Running: Yes 和 Slave_SQL_Running: Yes 則說明主從配置成功
# 還能夠到master上執行 Mysql>show global status like 「rpl%」; 若是Rpl_semi_sync_master_clients 是2.說明半同步複製正常

安裝MHA

下載MHA Node 0.54: https://code.google.com/p/mysql-master-ha/downloads/detail?name=mha4mysql-node_0.54-0_all.deb&can=2&q=

和 MHA Manager 0.55: https://code.google.com/p/mysql-master-ha/downloads/detail?name=mha4mysql-manager_0.55-0_all.deb&can=2&q=

其餘版本的文件在: https://code.google.com/p/mysql-master-ha/downloads/list

先在4臺機器上安裝MHA Node:

apt-get install libdbd-mysql-perl
dpkg -i mha4mysql-node_0.54-0_all.deb

在manager/host1 上安裝MHA Manager:

apt-get install libdbd-mysql-perl
apt-get install libconfig-tiny-perl
apt-get install liblog-dispatch-perl
apt-get install libparallel-forkmanager-perl
dpkg -i mha4mysql-manager_0.55-0_all.deb
mkdir -p /masterha/app1/

在manager上建立配置文件/etc/app1.cnf, 內容以下:

[server default]
manager_workdir=/masterha/app1
manager_log=/masterha/app1/manager.log
#remote_workdir=/usr/local/mysql
#mysql user and password
user=root
password=root
ssh_user=root
repl_user=repl
repl_password=repl
ping_interval=1
shutdown_script=""
#master_ip_failover_script=/usr/local/bin/master_ip_failover
#master_ip_online_change_script=/usr/local/bin/master_ip_online_change_script
#report_script=""

[server1]
hostname=master
master_binlog_dir=/var/log/mysql
candidate_master=1

[server2]
hostname=172.16.21.50
master_binlog_dir=/var/log/mysql
candidate_master=1
[server3]

hostname=172.16.21.48
master_binlog_dir=/var/log/mysql
no_master=1

而後給mysql賦權限, 在3臺mysql機器上執行以下語句:

mysql> grant all on *.* to root@'172.16.21.15' identified by 'root';
mysql> grant all on *.* to root@'172.16.21.23' identified by 'root';
mysql> grant all on *.* to root@'172.16.21.50' identified by 'root';
mysql> grant all on *.* to root@'172.16.21.48' identified by 'root';

或者也可執行以下語句:

mysql> grant all on *.* to root@'172.16.21.%' identified by 'root';

而後創建ssh無密碼登陸環境:

在manager上:

ssh-keygen -t rsa
ssh-copy-id root@172.16.21.23
ssh-copy-id root@172.16.21.50
ssh-copy-id root@172.16.21.48

在master上:

ssh-keygen -t rsa
ssh-copy-id root@172.16.21.50
ssh-copy-id root@172.16.21.48

在備選master上:

ssh-keygen -t rsa
ssh-copy-id root@172.16.21.23
ssh-copy-id root@172.16.21.48

在slave上:

ssh-keygen -t rsa
ssh-copy-id root@172.16.21.23
ssh-copy-id root@172.16.21.50

最後在manager上執行ssh登陸檢查:

masterha_check_ssh --conf=/etc/app1.cnf

和複製狀況檢查:

masterha_check_repl --conf=/etc/app1.cnf

而後能夠啓動manager:

nohup masterha_manager --conf=/etc/app1.cnf < /dev/null > /masterha/app1/manager.log 2>&1 &

檢查manager狀態:

masterha_check_status --conf=/etc/app1.cnf

中止manager:

masterha_stop --conf=/etc/app1.cnf
# 若是不能中止, 加 --abort選項

在備選master和slave節點 crontab -e 添加計劃任務

00 00 * * * /usr/local/bin/purge_relay_logs –user=root –password=root –disable_relay_log_purge >> /var/log/purge_relay_logs.log 2>&1

測試和恢復MHA

manager上 tail -f /masterha/app1/manager.log 監控log

而後在master上 echo c > /proc/sysrq-trigger 使其死機

在log裏能夠看到master轉移到備選master了

除了被動轉移master,還能夠手動轉移master,以下:

masterha_master_switch --conf=/etc/app1.cnf --master_state=dead --dead_master_host=...
masterha_master_switch --conf=/etc/app1.cnf --master_state=alive --new_master_host=...

注:針對原來的MySQL主服務器是否已經宕機,執行命令所需的參數有所不一樣。

MHA有個不方便的地方是,不管宕機致使的master切換仍是手動切換master, 原來的master都不在MHA架構內了,從新啓動也不會加入,必須手動加入。

手動加入和上面的步驟相似,先把當前master數據複製到要加入的機器,而後change master,再start slave, 關鍵在作這一過程當中,系統不能寫入,這點要人命。

master_ip_failover, shutdown_script等腳本

MHA在配置文件裏設置使得一些腳本在特定時候被執行

shutdown_script: MHA用於關閉master的腳本,在代碼samples/scripts有一個樣例腳本power_manager, 腳本詳解可看:https://code.google.com/p/mysql-master-ha/wiki/Parameters#shutdown_script

master_ip_failover_script, master_ip_online_change_script: 發生在master切換的時候,爲了應用繼續可用,調用這兩個腳本作些處理。refs:

說到Failover,一般有兩種方式:一種是虛擬IP地址,一種是全局配置文件。
MHA並無限定使用哪種方式,而是讓用戶本身選擇,虛擬IP地址的方式會牽扯到其它的軟件,這裏就不贅述了,
如下簡單說說全局配置文件,以PHP爲實現語言,代碼以下:

#!/usr/bin/env php
<?php
$longopts = array(
    'command:',
    'ssh_user:',
    'orig_master_host:',
    'orig_master_ip:',
    'orig_master_port:',
    'new_master_host::',
    'new_master_ip::',
    'new_master_port::',
);

$options = getopt(null, $longopts);

if ($options['command'] == 'start') {
    $params = array(
        'ip'   => $options['new_master_ip'],
        'port' => $options['new_master_port'],
    );

    $string = '<?php return ' . var_export($params, true) . '; ?>';

    file_put_contents('config.php', $string, LOCK_EX);
}

exit(0);
?>
注:用其它語言實現這個腳本也是OK的,最後別忘了給腳本加上可執行屬性。

若是要測試效果的話,能夠kill掉當前的MySQL主服務器,稍等片刻,MHA就會把某臺MySQL從服務器提高爲新的MySQL主服務器,
並調用master_ip_failover_script腳本,
如上所示,咱們在master_ip_failover_script腳本里能夠把新的MySQL主服務器的ip和port信息持久化到配置文件裏,
這樣應用就可使用新的配置了。

有時候須要手動切換MySQL主服務器,可使用masterha_master_switch命令,
不過它調用的不是master_ip_failover_script腳本,而是master_ip_online_change_script腳本,但調用參數相似,腳本能夠互用。

虛擬ip涉及到其餘軟件,咱們稍後講

report_script: You might want to send a report (i.e. e-mail) when failover has completed or ended with errors. 接受以下參數:

--orig_master_host=(dead master's hostname)
--new_master_host=(new master's hostname)
--new_slave_hosts=(new slaves' hostnames, delimited by commas)
--subject=(mail subject)
--body=(body)

這些腳本在代碼包裏都有示例,但都是perl的,你能夠用其餘腳本語言本身來寫。

配置虛擬IP

有個簡單的方法添加虛擬ip, 用ifconfig命令, 參考此文章:http://blog.csdn.net/csfreebird/article/details/7996318

添加VIP:

/sbin/ifconfig eth0:1 172.16.21.119/24

刪除VIP:

/sbin/ifconfig eth0:1 down

把配置寫入/etc/network/interfaces, 使其重啓有效:

auto lo
iface lo inet loopback

auto eth0:0
iface eth0:0 inet static
name Ethernet alias LAN card
address 10.112.18.191
netmask 255.255.255.0
broadcast 10.112.18.255
network 10.112.18.0

網上找了一個master_ip_failover腳本就是用此方法更改VIP:

#!/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.21.119/24';  # Virtual IP
my $key = "1";
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$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" ) {

        # $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 "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" ) {

        # 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 "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";
        `ssh $ssh_user\@cluster1 \" $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 $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";
}

將此文檔複製兩次到/usr/local/bin, 分別命名爲master_ip_failover 和master_ip_online_change_script

而後將/etc/app1.cnf 中下面兩行註釋去掉:

master_ip_failover_script=/usr/local/bin/master_ip_failover
master_ip_online_change_script=/usr/local/bin/master_ip_online_change_script
相關文章
相關標籤/搜索