Mysql高可以之MHA搭建


系统:CentOS6.5_X86_64
Mysql:MySQL-5.6.17-1.el6.x86_64

监控机(Manager):192.168.1.101
主库(Master):192.168.1.102
备主(Candicate Master):192.168.1.103
从库(Slave):192.168.1.104
虚拟IP(VIP):192.168.1.105


一、安装MySQL数据库(主、备、从)
#yum install -y MySQL-server
#yum install -y MySQL-client
#yum install -y MySQL-shared-compat (可以解决一些兼容性,可以不装)




二、主备从数据同步设置(双主一从模式)
要点:负责在主、备、从服务器传输各种修改动作的媒介是主服务器的二进制变更日志,这个日志记载着需要传输给从服务器的各种修改动作。因此,主服务器必须激活二进制日志功能。从服务器必须具备足以让它连接主服务器并请求主服务器把二进制变更日志传输给它的权限。

2.1.(主、备、从)修改my.cnf文件
主库:
在[mysql]标签下添加信息
#vim /etc/my.conf
erver_id=1
log-bin=master1-bin
log-bin-index=master1-bin.index
relay_log=mysql-relay-bin
relay_log_index=mysql-relay-bin.index
log_slave_updates= 1
sync_binlog=1
max_binlog_size= 1G
expire_logs_days = 15

备主:
在[mysql]标签下添加信息
#vim /etc/my.conf
server_id=2
log-bin=master2-bin
log-bin-index=master2-bin.index
relay_log=mysql-relay-bin
relay_log_index=mysql-relay-bin.index
log_slave_updates= 1
max_binlog_size= 1G
expire_logs_days = 15

从库:
在[mysql]标签下添加信息
#vim /etc/my.conf
server_id=3
log-bin=slave-bin
log-bin-index=slave-bin.index
relay_log=mysql-relay-bin
relay_log_index=mysql-relay-bin.index
log_slave_updates= 1
sync_binlog=1
max_binlog_size= 1G
expire_logs_days = 15
read_only = 1

server_id是必须的,而且唯一。slave没有必要开启二进制日志,但是在一些情况下,必须设置,例如:如果slave为其它slave的master,必须设置bin_log。这里开启了二进制日志并设置了显示的命名(默认名称为hostname,但是,如果hostname改变则会出现问题)。
relay_log配置中继日志,log_slave_updates表示slave将复制事件写进自己的二进制日志。
有些人开启了slave的二进制日志,却没有设置log_slave_updates,然后查看slave的数据是否改变,这是一种错误的配置。所以,尽量使用read_only,它防止改变数据(除了特殊的线程)。


2.2.(主、备、从)启动MySQL
#service mysql start

#/etc/init.d/mysql start


2.3.主库创建数据复制专用账号
Master的数据库中建立一个备份帐户:每个slave使用标准的MySQL用户名和密码连接master。进行复制操作的用户会授予REPLICATION SLAVE权限。用户名的密码都会存储在文本文件master.info中。

主库为备主和从库创建数据复制专用账号
mysql> GRANT REPLICATION SLAVE,RELOAD,SUPER ON *.* TO mstbk@ '192.168.1.103' IDENTIFIED BY '1234';
mysql> GRANT REPLICATION SLAVE,RELOAD,SUPER ON *.* TO mstbk@ '192.168.1.104' IDENTIFIED BY '1234';
mysql> FLUSH PRIVILEGES;

建立一个帐户mstbk,并且只能允许从192.168.1.103和192.168.1.104这两个地址上来登陆,密码是1234。
(如果因为mysql版本新旧密码算法不同,可以设置:
set password for 'mstbk'@'192.168.1.103'=old_password('1234'))



2.4.备库创建数据复制专用账号
备主为主库创建数据复制专用账号
mysql> GRANT REPLICATION SLAVE,RELOAD,SUPER ON *.* TO canbk@ '192.168.1.102' IDENTIFIED BY '1234';
mysql> FLUSH PRIVILEGES;


2.5.(主、备、从)执行change master操作
让备库、从库连接主库,并开始重做master二进制日志中的事件。不应该用配置文件进行该操作,而应该使用CHANGE MASTER TO语句,该语句可以完全取代对配置文件的修改,而且它可以为slave指定不同的master,而不需要停止服务器。

1)主库:
主库查看当前日志得到file和position信息
mysql> SHOW MASTER STATUS;

2)备主:
mysql> CHANGE MASTER TO MASTER_HOST='192.168.1.102',MASTER_USER='mstbk',MASTER_PASSWORD='1234',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=0;
其中MASTER_LOG_FILE和MASTER_LOG_POS是主库查询得到的。

启动同步
mysql> START SLAVE;

查看同步信息
mysql> SHOW SLAVE STATUS\G;

备库查看当前日志得到file和position信息
mysql> SHOW MASTER STATUS;

3)从库:
mysql> CHANGE MASTER TO MASTER_HOST='192.168.1.102',MASTER_USER='mstbk',MASTER_PASSWORD='1234',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=0;
其中MASTER_LOG_FILE和MASTER_LOG_POS是主库查询得到的。

启动同步
mysql> START SLAVE;

查看同步信息
mysql> SHOW SLAVE STATUS\G;

4)主库:
mysql> CHANGE MASTER TO MASTER_HOST='192.168.1.103',MASTER_USER='canbk',MASTER_PASSWORD='1234',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=0;
其中MASTER_LOG_FILE和MASTER_LOG_POS是备主库查询得到的。

启动同步
mysql> START SLAVE;

查看同步信息
mysql> SHOW SLAVE STATUS\G;


注意:
查看同步信息时只有Slave_IO_Running和Slave_SQL_Running为Yes状态表明数据同步是正常的。


2.6.验证
主库:
在主库中创建数据库mytest
mysql> CREATE DATABASE mytest;
查看创建结果
mysql> SHOW DATABASES;

备主:
查看创建结果
mysql> SHOW DATABASES;

从库:
查看创建结果
mysql> SHOW DATABASES;

如果在备库和从库中都有mytest生成,说明主从已经正常了。




三、配置SSH无密码登录(监控端、主、备、从)
监控端:
# ssh-keygen -t rsa
# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.102
# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.103
# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.104


主库:
# ssh-keygen -t rsa
# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.101
# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.103
# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.104

备主:
# ssh-keygen -t rsa
# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.101
# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.102
# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.104

从库:
# ssh-keygen -t rsa
# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.101
# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.102
# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.103

注意:
相互之间第一次登录时需要手动输入一次密码,之后就可以免密码登录了。



四、在(监控端、主、备、从)上安装MHA-Node
在四个Node上安装mha4mysql-node以及perl-DBD依赖包;
http://www.chocolee.cn/download/mha/

监控端:
#yum –y install perl-DBD-MySQL
#rpm -ivh mha4mysql-node-0.54-0.el6.noarch.rpm

主库:
#yum –y install perl-DBD-MySQL
#rpm -ivh mha4mysql-node-0.54-0.el6.noarch.rpm

备主:
#yum –y install perl-DBD-MySQL
#rpm -ivh mha4mysql-node-0.54-0.el6.noarch.rpm

从库:
#yum –y install perl-DBD-MySQL
#rpm -ivh mha4mysql-node-0.54-0.el6.noarch.rpm



五、在监控端安装MHA-MANAGER
1.安装mha4mysql-manager及相关软件
在http://www.chocolee.cn/download/mha/下载mha4mysql-manager

#yum –y install perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager
#rpm -ivh mha4mysql-manager-0.55-0.el6.noarch.rpm

注意:
需要注意的是mha-manager和mha-node版本必须一致

2.设置MHA配置文件
#mkdir /etc/masterha/
#mkdir /var/log/masterha/app1/
#mkdir /var/log/masterha/

#vim /etc/masterha/app1.cnf
[server default]   
# mysql user and password   
user=root
password=12345678
ssh_user=root

# working directory on the manager
manager_workdir=/var/log/masterha/app1
manager_log=/var/log/masterha/app1/app1.log

# working directory on MySQL servers
remote_workdir=/var/log/masterha/app1
master_binlog_dir=/var/lib/mysql/
check_repl_delay=0
master_ip_failover_script=/etc/masterha/script/master_ip_failover
master_ip_online_change_script=/etc/masterha/script/master_ip_online_change_script


[server1]
hostname=192.168.1.102
candidate_master=1     
[server2]
hostname=192.168.1.103
candidate_master=1     
[server3]
hostname=192.168.1.104
no_master=1


3.编辑master_ip_failover和master_ip_online_change_script主备切换脚本
#mkdir /etc/masterha/script/

3.1设置自动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,
    $orig_master_user,$orig_master_password,$new_master_user,$new_master_password,
);
my $vip = '192.168.1.105'; # Virtual IP
my $gateway = '192.168.1.1';#Gateway IP
my $interface = 'eth0'
my $key = "1";
my $ssh_start_vip = "/sbin/ifconfig $interface:$key $vip;/sbin/arping -I $interface -c 3 -s $vip $gateway >/dev/null 2>&1";
my $ssh_stop_vip = "/sbin/ifconfig $interface:$key down";
my $ssh_user="root";

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,
    'orig_master_user=s' => \$orig_master_user,
    'orig_master_password=s' => \$orig_master_password,
    'new_master_user=s' => \$new_master_user,
    'new_master_password=s' => \$new_master_password,
);
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";
}


3.2设置手动切换时候的切换脚本
拷贝master_ip_failover重命名为master_ip_online_change_script
#cd /etc/masterha/script/
#cp master_ip_failover master_ip_online_change_script

3.3设置备主为read_only
当前是主主互备构架,且主库工作正常,则设置candicate主机192.168.1.103以及其他从机均为read_only,从库已经在my.cnf配置文件中配置了。
查看数据库的read_only状态
mysql> SHOW VARIABLES LIKE 'read_only';
如果未开启(ON状态)则开启:
mysql> SET GLOBAL read_only=1;

3.4设置(主、备、从)relay_log_purge
关闭(主、备、从)relay_log_purge即MySQL的自动清理日志功能;
查看数据库是否的relay_log_purge状态
mysql> SHOW VARIABLES LIKE 'relay_log_purge';
如果未关闭(OFF状态)则关闭:
mysql> SET GLOBAL relay_log_purge=0;

3.5管理relay log文件
关闭relay_log_purge后必须对relay log文件进行有效的管理;使用定时任务来定时清理relay log.
编辑定时任务
#crontab -e
0 5 * * * app /usr/bin/purge_relay_logs --user=root --password=12345678 --disable_relay_log_purge >> /var/log/masterha/purge_relay_logs.log 2>&1
注意:这里的用户名密码是MySQL的,如果root没有密码及不需要给出--password=参数项

重启定时任务服务
#service crond restart

3.6监控端开启MHA-MANAGER监控服务
# masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf
推荐使用后台进程模式运营:
# nohup masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf < /dev/null > /var/log/masterha/app1/app1.log 2>&1 &



六、检查设置
1.检查SSH无密码登录
在监控执行以下命令:
#masterha_check_ssh --conf=/etc/masterha/app1.cnf
执行后的结果中出现‘All SSH connection tests passed successfully.’说明SSH无密码登录配置成功。

2.检查主备从数据复制状态
#masterha_check_repl --conf=/etc/masterha/app1.cnf
执行后将给出是否OK的结果。

3.检查manager运营状态:
# masterha_check_status --conf=/etc/masterha/app1.cnf

4.手动切换检测
情景一:手工对dead master进行切换
# masterha_master_switch --master_state=dead --conf=/etc/masterha/app1.cnf --dead_master_host=192.168.1.102 --new_master_host=192.168.1.103
如果,MHA manager检测到没有dead的server,将报错,并结束failover:
Thu May 17 17:53:33 2012 - [info] Dead Servers:
Thu May 17 17:53:33 2012 - [error][/usr/lib/perl5/site_perl/5.8.8/MHA/MasterFailover.pm, ln181] None of server is dead. Stop failover.

情景二:当前master在正常运行情况的切换:

执行前要停止监听(manager)服务的运行
# masterha_stop --conf=/etc/masterha/app1.cnf
然后执行切换

#masterha_master_switch --conf=/etc/masterha/app1.cnf --master_state=alive --new_master_host=192.168.1.103
切换后,会给出切换结果;如果成功这是备主192.168.1.103称为了实际上的主机,而原来的主机192.168.1.102将被隔离。

5.自动切换
关闭主库MySQL服务后,将发生切换
注意:要保证切换且MHA是正常的,MHA-MANAGER监控服务是运行的。


七、切换后恢复双主一从的正常模式
情景:主库出现异常后发生了切换操作,当主库修好后需要恢复到双主一从的正常模式;

注意:
1)发生主备切换后,MHA-MANAGER监控服务会自动停掉,且在/var/log/masterha/app1/下面生成app1.failover.complete,若再次发生切换需要删除app1.failover.complete文件;
2)发生主备切换后,/etc/masterha/app1.cnf中异常的服务器信息将被自动删除,恢复时需要将被删除的服务器信息添加到配置文件中;

恢复步骤:
1.主库上的操作(192.168.1.102):
1.1正常启动主库
#service mysqld start;

1.2设置主库为read_only
查看数据库的read_only状态
mysql> SHOW VARIABLES LIKE 'read_only';
如果未开启(ON状态)则开启:
mysql> SET GLOBAL read_only=1;

1.3设置主库relay_log_purge
关闭主库relay_log_purge即MySQL的自动清理日志功能;
查看数据库是否的relay_log_purge状态
mysql> SHOW VARIABLES LIKE 'relay_log_purge';
如果未关闭(OFF状态)则关闭:
mysql> SET GLOBAL relay_log_purge=0;

1.4启用管理relay log文件的定时任务
编辑定时任务
#crontab -e
0 5 * * * app /usr/bin/purge_relay_logs --user=root --password=12345678 --disable_relay_log_purge >> /var/log/masterha/purge_relay_logs.log 2>&1

重启定时任务
#service crond restart

1.5恢复主库为备主的从库
主库查看同步信息是否正常
mysql> SHOW SLAVE STATUS\G;

1.6如果没有了同步信息,则重新建立:
1)查看备库日志信息:
备库查看当前日志得到file和position信息
mysql> SHOW MASTER STATUS;

2)主库(192.168.1.102):
mysql> CHANGE MASTER TO MASTER_HOST='192.168.1.103',MASTER_USER='canbk',MASTER_PASSWORD='1234',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=0;
其中MASTER_LOG_FILE和MASTER_LOG_POS是备主库查询得到的。

3)启动同步
mysql> START SLAVE;

4)查看同步信息
mysql> SHOW SLAVE STATUS\G;


2.备主上的操作(192.168.1.103):
这是的备主实际上已经成了主库对外提供服务器了,但我们仍然从逻辑上称呼它备主;

2.1恢复备库为主的从库
主库查看同步信息是否正常
mysql> SHOW SLAVE STATUS\G;

2.2如果没有了同步信息,则重新建立:
1)备主(192.168.1.103):
主库查看当前日志得到file和position信息
mysql> SHOW MASTER STATUS;

2)备主:
mysql> CHANGE MASTER TO MASTER_HOST='192.168.1.102',MASTER_USER='mstbk',MASTER_PASSWORD='1234',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=0;
其中MASTER_LOG_FILE和MASTER_LOG_POS是主库查询得到的。

3)启动同步
mysql> START SLAVE;

4)查看同步信息
mysql> SHOW SLAVE STATUS\G;

3.修复/etc/masterha/app1.cnf文件
将删除的主库信息加入配置文件
[server1]
hostname=192.168.1.102
candidate_master=1

4.删除app1.failover.complete
#rm  /var/log/masterha/app1/app1.failover.complete

5.检查主备从数据复制状态
#masterha_check_repl --conf=/etc/masterha/app1.cnf

6.开启MHA-MANAGER监控服务
# masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf
推荐使用后台进程模式运营:
# nohup masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf < /dev/null > /var/log/masterha/app1/app1.log 2>&1 &


参考:
http://www.cnblogs.com/jirglt/p/3549047.html
http://www.techsiteanalytics.com/index.php/2013/08/14/6428
http://blog.chinaunix.net/uid-14010457-id-3481261.html
http://www.cnblogs.com/yuanermen/p/3726572.html
http://blog.itpub.net/88305/viewspace-730135
http://www.linuxidc.com/Linux/2014-11/109460p2.htm