转一下大师兄的"MySQL高可用架构之MHA"

 

简介:php

MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton(现就任于Facebook公司)开发,是一套优秀的做为MySQL高可用性环境下故障切换和主从提高的高可用软件。在MySQL故障切换过程当中,MHA能作到在0~30秒以内自动完成数据库的故障切换操做,而且在进行故障切换的过程当中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。html

该软件由两部分组成:MHA Manager(管理节点)和MHA Node(数据节点)。MHA Manager能够单独部署在一台独立的机器上管理多个master-slave集群,也能够部署在一台slave节点上。MHA Node运行在每台MySQL服务器上,MHA Manager会定时探测集群中的master节点,当master出现故障时,它能够自动将最新数据的slave提高为新的master,而后将全部其余的slave从新指向新的master。整个故障转移过程对应用程序彻底透明。node

在MHA自动故障切换过程当中,MHA试图从宕机的主服务器上保存二进制日志,最大程度的保证数据的不丢失,但这并不老是可行的。例如,若是主服务器硬件故障或没法经过ssh访问,MHA无法保存二进制日志,只进行故障转移而丢失了最新的数据。使用MySQL 5.5的半同步复制,能够大大下降数据丢失的风险。MHA能够与半同步复制结合起来。若是只有一个slave已经收到了最新的二进制日志,MHA能够将最新的二进制日志应用于其余全部的slave服务器上,所以能够保证全部节点的数据一致性。mysql

目前MHA主要支持一主多从的架构,要搭建MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当master,一台充当备用master,另一台充当从库,由于至少须要三台服务器,出于机器成本的考虑,淘宝也在该基础上进行了改造,目前淘宝TMHA已经支持一主一从。另外对于想快速搭建的能够参考:MHA快速搭建linux

咱们本身使用其实也可使用1主1从,可是master主机宕机后没法切换,以及没法补全binlog。master的mysqld进程crash后,仍是能够切换成功,以及补全binlog的。sql

官方介绍:https://code.google.com/p/mysql-master-ha/shell

图01展现了如何经过MHA Manager管理多组主从复制。能够将MHA工做原理总结为以下:数据库

 

                                 ( 图01 )centos

(1)从宕机崩溃的master保存二进制日志事件(binlog events);安全

(2)识别含有最新更新的slave;

(3)应用差别的中继日志(relay log)到其余的slave;

(4)应用从master保存的二进制日志事件(binlog events);

(5)提高一个slave为新的master;

(6)使其余的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工具包(这些工具一般由MHA Manager的脚本触发,无需人为操做)主要包括如下几个工具:

save_binary_logs                保存和复制master的二进制日志
apply_diff_relay_logs           识别差别的中继日志事件并将其差别的事件应用于其余的slave
filter_mysqlbinlog              去除没必要要的ROLLBACK事件(MHA已再也不使用这个工具)
purge_relay_logs                清除中继日志(不会阻塞SQL线程)

注意:

为了尽量的减小主库硬件损坏宕机形成的数据丢失,所以在配置MHA的同时建议配置成MySQL 5.5的半同步复制。关于半同步复制原理各位本身进行查阅。(不是必须)

1.部署MHA

接下来部署MHA,具体的搭建环境以下(全部操做系统均为centos 6.2 64bit,不是必须,server03和server04是server02的从,复制环境搭建后面会简单演示,可是相关的安全复制不会详细说明,须要的童鞋请参考前面的文章,MySQL Replication须要注意的问题):

角色                    ip地址          主机名          server_id                  类型
Monitor host            192.168.0.20    server01            -                      监控复制组
Master                  192.168.0.50    server02            1                      写入
Candicate master        192.168.0.60    server03            2                      读
Slave                   192.168.0.70    server04            3                      读

其中master对外提供写服务,备选master(实际的slave,主机名server03)提供读服务,slave也提供相关的读服务,一旦master宕机,将会把备选master提高为新的master,slave指向新的master

(1)在全部节点安装MHA node所需的perl模块(DBD:mysql),安装脚本以下:

复制代码
[root@192.168.0.50 ~]# cat install.sh 
#!/bin/bash
wget http://xrl.us/cpanm --no-check-certificate
mv cpanm /usr/bin
chmod 755 /usr/bin/cpanm
cat > /root/list << EOF
install DBD::mysql
EOF
for package in `cat /root/list`
do
    cpanm $package
done
[root@192.168.0.50 ~]# 
复制代码

若是有安装epel源,也可使用yum安装

yum install perl-DBD-MySQL -y

(2)在全部的节点安装mha node:

wget http://mysql-master-ha.googlecode.com/files/mha4mysql-node-0.53.tar.gz
tar xf mha4mysql-node-0.53.tar.gz
cd mha4mysql-node-0.53
perl Makefile.PL
make && make install

安装完成后会在/usr/local/bin目录下生成如下脚本文件:

复制代码
[root@192.168.0.50 bin]# pwd
/usr/local/bin
[root@192.168.0.50 bin]# ll
total 40
-r-xr-xr-x 1 root root 15498 Apr 20 10:05 apply_diff_relay_logs
-r-xr-xr-x 1 root root  4807 Apr 20 10:05 filter_mysqlbinlog
-r-xr-xr-x 1 root root  7401 Apr 20 10:05 purge_relay_logs
-r-xr-xr-x 1 root root  7263 Apr 20 10:05 save_binary_logs
[root@192.168.0.50 bin]# 
复制代码

关于上面脚本的功能,上面已经介绍过了,这里再也不重复了。

2.安装MHA Manager

MHA Manager中主要包括了几个管理员的命令行工具,例如master_manger,master_master_switch等。MHA Manger也依赖于perl模块,具体以下:

(1)安装MHA Node软件包以前须要安装依赖。我这里使用yum完成,没有epel源的可使用上面提到的脚本(epel源安装也简单)。注意:在MHA Manager的主机也是须要安装MHA Node。

rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
yum install perl-DBD-MySQL -y

安装MHA Node软件包,和上面的方法同样,以下:

wget http://mysql-master-ha.googlecode.com/files/mha4mysql-node-0.53.tar.gz
tar xf mha4mysql-node-0.53.tar.gz
cd mha4mysql-node-0.53
perl Makefile.PL
make && make install

(2)安装MHA Manager。首先安装MHA Manger依赖的perl模块(我这里使用yum安装):

yum install perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes -y

安装MHA Manager软件包:

wget http://mysql-master-ha.googlecode.com/files/mha4mysql-manager-0.53.tar.gz
tar xf mha4mysql-manager-0.53.tar.gz 
cd mha4mysql-manager-0.53
perl Makefile.PL
make && make install

安装完成后会在/usr/local/bin目录下面生成如下脚本文件,前面已经说过这些脚本的做用,这里再也不重复

复制代码
[root@192.168.0.20 bin]# pwd
/usr/local/bin
[root@192.168.0.20 bin]# ll
total 76
-r-xr-xr-x 1 root root 15498 Apr 20 10:58 apply_diff_relay_logs
-r-xr-xr-x 1 root root  4807 Apr 20 10:58 filter_mysqlbinlog
-r-xr-xr-x 1 root root  1995 Apr 20 11:33 masterha_check_repl
-r-xr-xr-x 1 root root  1779 Apr 20 11:33 masterha_check_ssh
-r-xr-xr-x 1 root root  1865 Apr 20 11:33 masterha_check_status
-r-xr-xr-x 1 root root  3201 Apr 20 11:33 masterha_conf_host
-r-xr-xr-x 1 root root  2517 Apr 20 11:33 masterha_manager
-r-xr-xr-x 1 root root  2165 Apr 20 11:33 masterha_master_monitor
-r-xr-xr-x 1 root root  2373 Apr 20 11:33 masterha_master_switch
-r-xr-xr-x 1 root root  3749 Apr 20 11:33 masterha_secondary_check
-r-xr-xr-x 1 root root  1739 Apr 20 11:33 masterha_stop
-r-xr-xr-x 1 root root  7401 Apr 20 10:58 purge_relay_logs
-r-xr-xr-x 1 root root  7263 Apr 20 10:58 save_binary_logs
[root@192.168.0.20 bin]# 
复制代码

复制相关脚本到/usr/local/bin目录(软件包解压缩后就有了,不是必须,由于这些脚本不完整,须要本身修改,这是软件开发着留给咱们本身发挥的,若是开启下面的任何一个脚本对应的参数,而对应这里的脚本又没有修改,则会抛错,本身被坑的很惨)

复制代码
[root@192.168.0.20 scripts]# pwd
/root/mha4mysql-manager-0.53/samples/scripts
[root@192.168.0.20 scripts]# ll
total 32
-rwxr-xr-x 1 root root  3443 Jan  8  2012 master_ip_failover                #自动切换时vip管理的脚本,不是必须,若是咱们使用keepalived的,咱们能够本身编写脚本完成对vip的管理,好比监控mysql,若是mysql异常,咱们中止keepalived就行,这样vip就会自动漂移
-rwxr-xr-x 1 root root  9186 Jan  8  2012 master_ip_online_change           #在线切换时vip的管理,不是必须,一样能够能够自行编写简单的shell完成
-rwxr-xr-x 1 root root 11867 Jan  8  2012 power_manager                     #故障发生后关闭主机的脚本,不是必须
-rwxr-xr-x 1 root root  1360 Jan  8  2012 send_report                       #因故障切换后发送报警的脚本,不是必须,可自行编写简单的shell完成。
[root@192.168.0.20 scripts]# cp * /usr/local/bin/
[root@192.168.0.20 scripts]# 
复制代码

3.配置SSH登陆无密码验证(使用key登陆,工做中经常使用)个人测试环境已是使用key登陆,服务器之间无需密码验证的。关于配置使用key登陆,我想我再也不重复。可是有一点须要注意:不能禁止 password 登录,不然会出现错误

4.搭建主从复制环境

注意:binlog-do-db 和 replicate-ignore-db 设置必须相同。 MHA 在启动时候会检测过滤规则,若是过滤规则不一样,MHA 不启动监控和故障转移。

(1)在server02上执行备份(192.168.0.50)

[root@192.168.0.50 ~]# mysqldump --master-data=2 --single-transaction -R --triggers -A > all.sql

其中--master-data=2表明备份时刻记录master的Binlog位置和Position,--single-transaction意思是获取一致性快照,-R意思是备份存储过程和函数,--triggres的意思是备份触发器,-A表明备份全部的库。更多信息请自行mysqldump --help查看。

(2)在server02上建立复制用户:

复制代码
mysql> grant replication slave on *.* to 'repl'@'192.168.0.%' identified by '123456';
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> 
复制代码

(3)查看主库备份时的binlog名称和位置,MASTER_LOG_FILE和MASTER_LOG_POS:

[root@192.168.0.50 ~]# head -n 30 all.sql | grep 'CHANGE MASTER TO'
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000010', MASTER_LOG_POS=112;
[root@192.168.0.50 ~]# 

(4)把备份复制到server03和server04,也就是192.168.0.60和192.168.0.70

scp all.sql server03:/data/
scp all.sql server04:/data/

(5)导入备份到server03,执行复制相关命令

mysql < /data/all.sql
复制代码
mysql> CHANGE MASTER TO MASTER_HOST='192.168.0.50',MASTER_USER='repl', MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000010',MASTER_LOG_POS=112;
Query OK, 0 rows affected (0.02 sec)

mysql> start slave;
Query OK, 0 rows affected (0.01 sec)

mysql> 
复制代码

查看复制状态(能够看见复制成功):

[root@192.168.0.60 ~]# mysql -e 'show slave status\G' | egrep 'Slave_IO|Slave_SQL'
               Slave_IO_State: Waiting for master to send event
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
[root@192.168.0.60 ~]# 

(6)在server04(192.168.0.70)上搭建复制环境,操做和上面同样。

mysql < /data/all.sql
复制代码
mysql> CHANGE MASTER TO MASTER_HOST='192.168.0.50',MASTER_USER='repl', MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000010',MASTER_LOG_POS=112;
Query OK, 0 rows affected (0.07 sec)

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

mysql> 
复制代码

查看复制状态:

[root@192.168.0.70 ~]# mysql -e 'show slave status\G' | egrep 'Slave_IO|Slave_SQL'
               Slave_IO_State: Waiting for master to send event
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
[root@192.168.0.70 ~]# 

(7)两台slave服务器设置read_only(从库对外提供读服务,只因此没有写进配置文件,是由于随时slave会提高为master

[root@192.168.0.60 ~]# mysql -e 'set global read_only=1'
[root@192.168.0.60 ~]# 
[root@192.168.0.70 ~]# mysql -e 'set global read_only=1'
[root@192.168.0.70 ~]# 

(8)建立监控用户(在master上执行,也就是192.168.0.50):

复制代码
mysql> grant all privileges on *.* to 'root'@'192.168.0.%' identified  by '123456';
Query OK, 0 rows affected (0.00 sec)

mysql> flush  privileges;
Query OK, 0 rows affected (0.01 sec)

mysql> 
复制代码

到这里整个集群环境已经搭建完毕,剩下的就是配置MHA软件了。

5.配置MHA

(1)建立MHA的工做目录,而且建立相关配置文件(在软件包解压后的目录里面有样例配置文件)。

[root@192.168.0.20 ~]# mkdir -p /etc/masterha
[root@192.168.0.20 ~]# cp mha4mysql-manager-0.53/samples/conf/app1.cnf /etc/masterha/
[root@192.168.0.20 ~]# 

修改app1.cnf配置文件,修改后的文件内容以下(注意,配置文件中的注释须要去掉,我这里是为了解释清楚):

复制代码
[root@192.168.0.20 ~]# cat /etc/masterha/app1.cnf 
[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         //设置mysql中root用户的密码,这个密码是前文中建立监控用户的那个密码
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            
shutdown_script="" //设置故障发生后关闭故障主机脚本(该脚本的主要做用是关闭主机放在发生脑裂,这里没有使用) ssh_user=root //设置ssh的登陆用户名 [server1] hostname=192.168.0.50 port=3306 [server2] hostname=192.168.0.60 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=192.168.0.70 port=3306 [root@192.168.0.20 ~]#
复制代码

(2)设置relay log的清除方式(在每一个slave节点上):

[root@192.168.0.60 ~]# mysql -e 'set global relay_log_purge=0'
[root@192.168.0.70 ~]# mysql -e 'set global relay_log_purge=0'

注意:

MHA在发生切换的过程当中,从库的恢复过程当中依赖于relay log的相关信息,因此这里要将relay log的自动清除设置为OFF,采用手动清除relay log的方式。在默认状况下,从服务器上的中继日志会在SQL线程执行完毕后被自动删除。可是在MHA环境中,这些中继日志在恢复其余从服务器时可能会被用到,所以须要禁用中继日志的自动删除功能。按期清除中继日志须要考虑到复制延时的问题。在ext3的文件系统下,删除大的文件须要必定的时间,会致使严重的复制延时。为了不复制延时,须要暂时为中继日志建立硬连接,由于在linux系统中经过硬连接删除大文件速度会很快。(在mysql数据库中,删除大表时,一般也采用创建硬连接的方式)

MHA节点中包含了pure_relay_logs命令工具,它能够为中继日志建立硬连接,执行SET GLOBAL relay_log_purge=1,等待几秒钟以便SQL线程切换到新的中继日志,再执行SET GLOBAL relay_log_purge=0。

pure_relay_logs脚本参数以下所示:

复制代码
--user mysql                      用户名
--password mysql                  密码
--port                            端口号
--workdir                         指定建立relay log的硬连接的位置,默认是/var/tmp,因为系统不一样分区建立硬连接文件会失败,故须要执行硬连接具体位置,成功执行脚本后,硬连接的中继日志文件被删除
--disable_relay_log_purge         默认状况下,若是relay_log_purge=1,脚本会什么都不清理,自动退出,经过设定这个参数,当relay_log_purge=1的状况下会将relay_log_purge设置为0。清理relay log以后,最后将参数设置为OFF。
复制代码

(3)设置按期清理relay脚本(两台slave服务器)

复制代码
[root@192.168.0.60 ~]# cat purge_relay_log.sh 
#!/bin/bash
user=root
passwd=123456
port=3306
log_dir='/data/masterha/log'
work_dir='/data'
purge='/usr/local/bin/purge_relay_logs'

if [ ! -d $log_dir ]
then
   mkdir $log_dir -p
fi

$purge --user=$user --password=$passwd --disable_relay_log_purge --port=$port --workdir=$work_dir >> $log_dir/purge_relay_logs.log 2>&1
[root@192.168.0.60 ~]# 
复制代码

添加到crontab按期执行

[root@192.168.0.60 ~]# crontab -l
0 4 * * * /bin/bash /root/purge_relay_log.sh
[root@192.168.0.60 ~]# 

purge_relay_logs脚本删除中继日志不会阻塞SQL线程。下面咱们手动执行看看什么状况。

复制代码
[root@192.168.0.60 ~]# purge_relay_logs --user=root --password=123456 --port=3306 -disable_relay_log_purge --workdir=/data/
2014-04-20 15:47:24: purge_relay_logs script started.
 Found relay_log.info: /data/mysql/relay-log.info
 Removing hard linked relay log files server03-relay-bin* under /data/.. done.
 Current relay log file: /data/mysql/server03-relay-bin.000002
 Archiving unused relay log files (up to /data/mysql/server03-relay-bin.000001) ...
 Creating hard link for /data/mysql/server03-relay-bin.000001 under /data//server03-relay-bin.000001 .. ok.
 Creating hard links for unused relay log files completed.
 Executing SET GLOBAL relay_log_purge=1; FLUSH LOGS; sleeping a few seconds so that SQL thread can delete older relay log files (if it keeps up); SET GLOBAL relay_log_purge=0; .. ok.
 Removing hard linked relay log files server03-relay-bin* under /data/.. done.
2014-04-20 15:47:27: All relay log purging operations succeeded.
[root@192.168.0.60 ~]# 
复制代码

6.检查SSH配置

检查MHA Manger到全部MHA Node的SSH链接状态:

复制代码
[root@192.168.0.20 ~]# masterha_check_ssh --conf=/etc/masterha/app1.cnf 
Sun Apr 20 17:17:39 2014 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Sun Apr 20 17:17:39 2014 - [info] Reading application default configurations from /etc/masterha/app1.cnf..
Sun Apr 20 17:17:39 2014 - [info] Reading server configurations from /etc/masterha/app1.cnf..
Sun Apr 20 17:17:39 2014 - [info] Starting SSH connection tests..
Sun Apr 20 17:17:40 2014 - [debug] 
Sun Apr 20 17:17:39 2014 - [debug]  Connecting via SSH from root@192.168.0.50(192.168.0.50:22) to root@192.168.0.60(192.168.0.60:22)..
Sun Apr 20 17:17:39 2014 - [debug]   ok.
Sun Apr 20 17:17:39 2014 - [debug]  Connecting via SSH from root@192.168.0.50(192.168.0.50:22) to root@192.168.0.70(192.168.0.70:22)..
Sun Apr 20 17:17:39 2014 - [debug]   ok.
Sun Apr 20 17:17:40 2014 - [debug] 
Sun Apr 20 17:17:40 2014 - [debug]  Connecting via SSH from root@192.168.0.60(192.168.0.60:22) to root@192.168.0.50(192.168.0.50:22)..
Sun Apr 20 17:17:40 2014 - [debug]   ok.
Sun Apr 20 17:17:40 2014 - [debug]  Connecting via SSH from root@192.168.0.60(192.168.0.60:22) to root@192.168.0.70(192.168.0.70:22)..
Sun Apr 20 17:17:40 2014 - [debug]   ok.
Sun Apr 20 17:17:41 2014 - [debug] 
Sun Apr 20 17:17:40 2014 - [debug]  Connecting via SSH from root@192.168.0.70(192.168.0.70:22) to root@192.168.0.50(192.168.0.50:22)..
Sun Apr 20 17:17:40 2014 - [debug]   ok.
Sun Apr 20 17:17:40 2014 - [debug]  Connecting via SSH from root@192.168.0.70(192.168.0.70:22) to root@192.168.0.60(192.168.0.60:22)..
Sun Apr 20 17:17:41 2014 - [debug]   ok.
Sun Apr 20 17:17:41 2014 - [info] All SSH connection tests passed successfully.
复制代码

能够看见各个节点ssh验证都是ok的。

7.检查整个复制环境情况。

经过masterha_check_repl脚本查看整个集群的状态

复制代码
[root@192.168.0.20 ~]# masterha_check_repl --conf=/etc/masterha/app1.cnf
Sun Apr 20 18:36:55 2014 - [info] Checking replication health on 192.168.0.60..
Sun Apr 20 18:36:55 2014 - [info]  ok.
Sun Apr 20 18:36:55 2014 - [info] Checking replication health on 192.168.0.70..
Sun Apr 20 18:36:55 2014 - [info]  ok.
Sun Apr 20 18:36:55 2014 - [info] Checking master_ip_failover_script status:
Sun Apr 20 18:36:55 2014 - [info]   /usr/local/bin/master_ip_failover --command=status --ssh_user=root --orig_master_host=192.168.0.50 --orig_master_ip=192.168.0.50 --orig_master_port=3306 
Bareword "FIXME_xxx" not allowed while "strict subs" in use at /usr/local/bin/master_ip_failover line 88.
Execution of /usr/local/bin/master_ip_failover aborted due to compilation errors.
Sun Apr 20 18:36:55 2014 - [error][/usr/local/share/perl5/MHA/MasterMonitor.pm, ln214]  Failed to get master_ip_failover_script status with return code 255:0.
Sun Apr 20 18:36:55 2014 - [error][/usr/local/share/perl5/MHA/MasterMonitor.pm, ln383] Error happend on checking configurations.  at /usr/local/bin/masterha_check_repl line 48
Sun Apr 20 18:36:55 2014 - [error][/usr/local/share/perl5/MHA/MasterMonitor.pm, ln478] Error happened on monitoring servers.
Sun Apr 20 18:36:55 2014 - [info] Got exit code 1 (Not master dead).

MySQL Replication Health is NOT OK!
复制代码

发现最后的结论说个人复制不是ok的。可是上面的信息明明说是正常的,本身也进数据库查看了。这里一直踩坑。一直纠结,后来无心中发现火丁笔记的博客,这才知道了缘由,原来Failover两种方式:一种是虚拟IP地址,一种是全局配置文件。MHA并无限定使用哪种方式,而是让用户本身选择,虚拟IP地址的方式会牵扯到其它的软件,好比keepalive软件,并且还要修改脚本master_ip_failover。(最后修改脚本后才没有这个报错,本身不懂perl也是折腾的半死,去年买了块表)

若是发现以下错误:

Can't exec "mysqlbinlog": No such file or directory at /usr/local/share/perl5/MHA/BinlogManager.pm line 99.
mysqlbinlog version not found!
Testing mysql connection and privileges..sh: mysql: command not found

解决方法以下,添加软链接(全部节点)

ln -s /usr/local/mysql/bin/mysqlbinlog /usr/local/bin/mysqlbinlog
ln -s /usr/local/mysql/bin/mysql /usr/local/bin/mysql

因此先暂时注释master_ip_failover_script= /usr/local/bin/master_ip_failover这个选项。后面引入keepalived后和修改该脚本之后再开启该选项。

[root@192.168.0.20 ~]# grep master_ip_failover /etc/masterha/app1.cnf
#master_ip_failover_script= /usr/local/bin/master_ip_failover
[root@192.168.0.20 ~]# 

再次进行状态查看:

复制代码
Sun Apr 20 18:46:08 2014 - [info] Checking replication health on 192.168.0.60..
Sun Apr 20 18:46:08 2014 - [info]  ok.
Sun Apr 20 18:46:08 2014 - [info] Checking replication health on 192.168.0.70..
Sun Apr 20 18:46:08 2014 - [info]  ok.
Sun Apr 20 18:46:08 2014 - [warning] master_ip_failover_script is not defined.
Sun Apr 20 18:46:08 2014 - [warning] shutdown_script is not defined.
Sun Apr 20 18:46:08 2014 - [info] Got exit code 0 (Not master dead).

MySQL Replication Health is OK.
复制代码

已经没有明显报错,只有两个警告而已,复制也显示正常了。
8.检查MHA Manager的状态:

经过master_check_status脚本查看Manager的状态:

[root@192.168.0.20 ~]# masterha_check_status --conf=/etc/masterha/app1.cnf
app1 is stopped(2:NOT_RUNNING).
[root@192.168.0.20 ~]# 

注意:若是正常,会显示"PING_OK",不然会显示"NOT_RUNNING",这表明MHA监控没有开启。
9.开启MHA Manager监控

[root@192.168.0.20 ~]# nohup masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/masterha/app1/manager.log 2>&1 &  
[1] 30867
[root@192.168.0.20 ~]# 

启动参数介绍:

--remove_dead_master_conf      该参数表明当发生主从切换后,老的主库的ip将会从配置文件中移除。

--manger_log                            日志存放位置

--ignore_last_failover                 在缺省状况下,若是MHA检测到连续发生宕机,且两次宕机间隔不足8小时的话,则不会进行Failover,之因此这样限制是为了不ping-pong效应。该参数表明忽略上次MHA触发切换产生的文件,默认状况下,MHA发生切换后会在日志目录,也就是上面我设置的/data产生app1.failover.complete文件,下次再次切换的时候若是发现该目录下存在该文件将不容许触发切换,除非在第一次切换后收到删除该文件,为了方便,这里设置为--ignore_last_failover。

查看MHA Manager监控是否正常:

[root@192.168.0.20 ~]# masterha_check_status --conf=/etc/masterha/app1.cnf
app1 (pid:20386) is running(0:PING_OK), master:192.168.0.50
[root@192.168.0.20 ~]# 

能够看见已经在监控了,并且master的主机为192.168.0.50

10.查看启动日志

复制代码
[root@192.168.0.20 ~]# tail -n20 /var/log/masterha/app1/manager.log
Sun Apr 20 19:12:01 2014 - [info]   Connecting to root@192.168.0.70(192.168.0.70:22).. 
  Checking slave recovery environment settings..
    Opening /data/mysql/relay-log.info ... ok.
    Relay log found at /data/mysql, up to server04-relay-bin.000002
    Temporary relay log file is /data/mysql/server04-relay-bin.000002
    Testing mysql connection and privileges.. done.
    Testing mysqlbinlog output.. done.
    Cleaning up test file(s).. done.
Sun Apr 20 19:12:01 2014 - [info] Slaves settings check done.
Sun Apr 20 19:12:01 2014 - [info] 
192.168.0.50 (current master)
 +--192.168.0.60
 +--192.168.0.70

Sun Apr 20 19:12:01 2014 - [warning] master_ip_failover_script is not defined.
Sun Apr 20 19:12:01 2014 - [warning] shutdown_script is not defined.
Sun Apr 20 19:12:01 2014 - [info] Set master ping interval 1 seconds.
Sun Apr 20 19:12:01 2014 - [info] Set 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
Sun Apr 20 19:12:01 2014 - [info] Starting ping health check on 192.168.0.50(192.168.0.50:3306)..
Sun Apr 20 19:12:01 2014 - [info] Ping(SELECT) succeeded, waiting until MySQL doesn't respond..
[root@192.168.0.20 ~]# 
复制代码

其中"Ping(SELECT) succeeded, waiting until MySQL doesn't respond.."说明整个系统已经开始监控了。
11.关闭MHA Manage监控

关闭很简单,使用masterha_stop命令完成。

[root@192.168.0.20 ~]# masterha_stop --conf=/etc/masterha/app1.cnf
Stopped app1 successfully.
[1]+  Exit 1                  nohup masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf --ignore_last_failover --manager_log=/data/mamanager.log
[root@192.168.0.20 ~]# 

12.配置VIP
vip配置能够采用两种方式,一种经过keepalived的方式管理虚拟ip的浮动;另一种经过脚本方式启动虚拟ip的方式(即不须要keepalived或者heartbeat相似的软件)。

1.keepalived方式管理虚拟ip,keepalived配置方法以下:

(1)下载软件进行并进行安装(两台master,准确的说一台是master,另一台是备选master,在没有切换之前是slave):

[root@192.168.0.50 ~]# wget http://www.keepalived.org/software/keepalived-1.2.12.tar.gz
复制代码
tar xf keepalived-1.2.12.tar.gz           
cd keepalived-1.2.12
./configure --prefix=/usr/local/keepalived
make &&  make install
cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/
cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
mkdir /etc/keepalived
cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
cp /usr/local/keepalived/sbin/keepalived /usr/sbin/
复制代码

(2)配置keepalived的配置文件,在master上配置(192.168.0.50)

复制代码
[root@192.168.0.50 ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
     notification_email {
     saltstack@163.com
   }
   notification_email_from dba@dbserver.com
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id MySQL-HA
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth1
    virtual_router_id 51
    priority 150
    advert_int 1
    nopreempt

    authentication {
    auth_type PASS
    auth_pass 1111
    }

    virtual_ipaddress {
        192.168.0.88
    }
}

[root@192.168.0.50 ~]# 
复制代码

其中router_id MySQL HA表示设定keepalived组的名称,将192.168.0.88这个虚拟ip绑定到该主机的eth1网卡上,而且设置了状态为backup模式,将keepalived的模式设置为非抢占模式(nopreempt),priority 150表示设置的优先级为150。下面的配置略有不一样,可是都是一个意思。
在候选master上配置(192.168.0.60)

复制代码
[root@192.168.0.60 ~]# cat /etc/keepalived/keepalived.conf 
! Configuration File for keepalived

global_defs {
     notification_email {
     saltstack@163.com
   }
   notification_email_from dba@dbserver.com
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id MySQL-HA
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth1
    virtual_router_id 51
    priority 120
    advert_int 1
    nopreempt

    authentication {
    auth_type PASS
    auth_pass 1111
    }

    virtual_ipaddress {
        192.168.0.88
    }
}

[root@192.168.0.60 ~]# 
复制代码

(3)启动keepalived服务,在master上启动并查看日志

复制代码
[root@192.168.0.50 ~]# /etc/init.d/keepalived start
Starting keepalived:                                       [  OK  ]
[root@192.168.0.50 ~]# tail -f /var/log/messages
Apr 20 20:22:16 192 Keepalived_healthcheckers[15334]: Opening file '/etc/keepalived/keepalived.conf'.
Apr 20 20:22:16 192 Keepalived_healthcheckers[15334]: Configuration is using : 7231 Bytes
Apr 20 20:22:16 192 kernel: IPVS: Connection hash table configured (size=4096, memory=64Kbytes)
Apr 20 20:22:16 192 kernel: IPVS: ipvs loaded.
Apr 20 20:22:16 192 Keepalived_healthcheckers[15334]: Using LinkWatch kernel netlink reflector...
Apr 20 20:22:19 192 Keepalived_vrrp[15335]: VRRP_Instance(VI_1) Transition to MASTER STATE
Apr 20 20:22:20 192 Keepalived_vrrp[15335]: VRRP_Instance(VI_1) Entering MASTER STATE
Apr 20 20:22:20 192 Keepalived_vrrp[15335]: VRRP_Instance(VI_1) setting protocol VIPs.
Apr 20 20:22:20 192 Keepalived_vrrp[15335]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth1 for 192.168.0.88
Apr 20 20:22:20 192 Keepalived_healthcheckers[15334]: Netlink reflector reports IP 192.168.0.88 added
Apr 20 20:22:25 192 Keepalived_vrrp[15335]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth1 for 192.168.0.88
复制代码

发现已经将虚拟ip 192.168.0.88绑定了网卡eth1上。
(4)查看绑定状况

[root@192.168.0.50 ~]# ip addr | grep eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 192.168.0.50/24 brd 192.168.0.255 scope global eth1
    inet 192.168.0.88/32 scope global eth1
[root@192.168.0.50 ~]# 

在另一台服务器,候选master上启动keepalived服务,并观察

复制代码
[root@192.168.0.60 ~]# /etc/init.d/keepalived start ; tail -f /var/log/messages
Starting keepalived:                                       [  OK  ]
Apr 20 20:26:18 192 Keepalived_vrrp[9472]: Registering gratuitous ARP shared channel
Apr 20 20:26:18 192 Keepalived_vrrp[9472]: Opening file '/etc/keepalived/keepalived.conf'.
Apr 20 20:26:18 192 Keepalived_vrrp[9472]: Configuration is using : 62976 Bytes
Apr 20 20:26:18 192 Keepalived_vrrp[9472]: Using LinkWatch kernel netlink reflector...
Apr 20 20:26:18 192 Keepalived_vrrp[9472]: VRRP_Instance(VI_1) Entering BACKUP STATE
Apr 20 20:26:18 192 Keepalived_vrrp[9472]: VRRP sockpool: [ifindex(3), proto(112), unicast(0), fd(10,11)]
Apr 20 20:26:18 192 Keepalived_healthcheckers[9471]: Netlink reflector reports IP 192.168.80.138 added
Apr 20 20:26:18 192 Keepalived_healthcheckers[9471]: Netlink reflector reports IP 192.168.0.60 added
Apr 20 20:26:18 192 Keepalived_healthcheckers[9471]: Netlink reflector reports IP fe80::20c:29ff:fe9d:6a9e added
Apr 20 20:26:18 192 Keepalived_healthcheckers[9471]: Netlink reflector reports IP fe80::20c:29ff:fe9d:6aa8 added
Apr 20 20:26:18 192 Keepalived_healthcheckers[9471]: Registering Kernel netlink reflector
Apr 20 20:26:18 192 Keepalived_healthcheckers[9471]: Registering Kernel netlink command channel
Apr 20 20:26:18 192 Keepalived_healthcheckers[9471]: Opening file '/etc/keepalived/keepalived.conf'.
Apr 20 20:26:18 192 Keepalived_healthcheckers[9471]: Configuration is using : 7231 Bytes
Apr 20 20:26:18 192 kernel: IPVS: Registered protocols (TCP, UDP, AH, ESP)
Apr 20 20:26:18 192 kernel: IPVS: Connection hash table configured (size=4096, memory=64Kbytes)
Apr 20 20:26:18 192 kernel: IPVS: ipvs loaded.
Apr 20 20:26:18 192 Keepalived_healthcheckers[9471]: Using LinkWatch kernel netlink reflector...
复制代码

从上面的信息能够看到keepalived已经配置成功。
注意:

上面两台服务器的keepalived都设置为了BACKUP模式,在keepalived中2种模式,分别是master->backup模式和backup->backup模式。这两种模式有很大区别。在master->backup模式下,一旦主库宕机,虚拟ip会自动漂移到从库,当主库修复后,keepalived启动后,还会把虚拟ip抢占过来,即便设置了非抢占模式(nopreempt)抢占ip的动做也会发生。在backup->backup模式下,当主库宕机后虚拟ip会自动漂移到从库上,当原主库恢复和keepalived服务启动后,并不会抢占新主的虚拟ip,即便是优先级高于从库的优先级别,也不会发生抢占。为了减小ip漂移次数,一般是把修复好的主库当作新的备库。

(5)MHA引入keepalived(MySQL服务进程挂掉时经过MHA 中止keepalived):

要想把keepalived服务引入MHA,咱们只须要修改切换是触发的脚本文件master_ip_failover便可,在该脚本中添加在master发生宕机时对keepalived的处理。

编辑脚本/usr/local/bin/master_ip_failover,修改后以下,我对perl不熟悉,因此我这里完整贴出该脚本(主库上操做,192.168.0.50)。

在MHA Manager修改脚本修改后的内容以下(参考资料比较少):

复制代码
#!/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 = '192.168.0.88';
my $ssh_start_vip = "/etc/init.d/keepalived start";
my $ssh_stop_vip = "/etc/init.d/keepalived stop";

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

        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";
        #`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() {
return 0  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@192.168.0.20 ~]# grep 'master_ip_failover_script' /etc/masterha/app1.cnf
master_ip_failover_script= /usr/local/bin/master_ip_failover
[root@192.168.0.20 ~]# 
复制代码
[root@192.168.0.20 ~]# masterha_check_repl --conf=/etc/masterha/app1.cnf  
Sun Apr 20 23:10:01 2014 - [info] Slaves settings check done.
Sun Apr 20 23:10:01 2014 - [info] 
192.168.0.50 (current master)
 +--192.168.0.60
 +--192.168.0.70

Sun Apr 20 23:10:01 2014 - [info] Checking replication health on 192.168.0.60..
Sun Apr 20 23:10:01 2014 - [info]  ok.
Sun Apr 20 23:10:01 2014 - [info] Checking replication health on 192.168.0.70..
Sun Apr 20 23:10:01 2014 - [info]  ok.
Sun Apr 20 23:10:01 2014 - [info] Checking master_ip_failover_script status:
Sun Apr 20 23:10:01 2014 - [info]   /usr/local/bin/master_ip_failover --command=status --ssh_user=root --orig_master_host=192.168.0.50 --orig_master_ip=192.168.0.50 --orig_master_port=3306 
Sun Apr 20 23:10:01 2014 - [info]  OK.
Sun Apr 20 23:10:01 2014 - [warning] shutdown_script is not defined.
Sun Apr 20 23:10:01 2014 - [info] Got exit code 0 (Not master dead).

MySQL Replication Health is OK.
复制代码

能够看见已经没有报错了。哈哈
 /usr/local/bin/master_ip_failover添加或者修改的内容意思是当主库数据库发生故障时,会触发MHA切换,MHA Manager会停掉主库上的keepalived服务,触发虚拟ip漂移到备选从库,从而完成切换。固然能够在keepalived里面引入脚本,这个脚本监控mysql是否正常运行,若是不正常,则调用该脚本杀掉keepalived进程。

2.经过脚本的方式管理VIP。这里是修改/usr/local/bin/master_ip_failover,也可使用其余的语言完成,好比php语言。使用php脚本编写的failover这里就不介绍了。修改完成后内容以下,并且若是使用脚本管理vip的话,须要手动在master服务器上绑定一个vip(发现修改修改对perl居然有感受了。难道我适合学Perl?^_^)

[root@192.168.0.50 ~]# /sbin/ifconfig eth1:1 192.168.0.88/24

经过脚原本维护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 = '192.168.0.88/24';
my $key = '1';
my $ssh_start_vip = "/sbin/ifconfig eth1:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth1:$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" ) {

        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() {
 return 0  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"; }
复制代码

为了防止脑裂发生,推荐生产环境采用脚本的方式来管理虚拟ip,而不是使用keepalived来完成。到此为止,基本MHA集群已经配置完毕。接下来就是实际的测试环节了。经过一些测试来看一下MHA究竟是如何进行工做的。下面将从MHA自动failover,咱们手动failover,在线切换三种方式来介绍MHA的工做状况。

一.自动Failover(必须先启动MHA Manager,不然没法自动切换,固然手动切换不须要开启MHA Manager监控。各位童鞋请参考前面启动MHA Manager)

测试环境再次贴一下,文章太长,本身都搞晕了。

角色                    ip地址          主机名          server_id               类型
Monitor host            192.168.0.20    server01            -                   监控复制组
Master                  192.168.0.50    server02            1                   写入
Candicate master        192.168.0.60    server03            2                   读
Slave                   192.168.0.70    server04            3                   读

自动failover模拟测试的操做步骤以下。
(1)使用sysbench生成测试数据(使用yum快速安装)

 yum install sysbench -y

在主库(192.168.0.50)上进行sysbench数据生成,在sbtest库下生成sbtest表,共100W记录。

[root@192.168.0.50 ~]# 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=123456 --db-driver=mysql --mysql-table-engine=innodb --oltp-test-mode=complex prepare

(2)停掉slave sql线程,模拟主从延时。(192.168.0.60)

mysql> stop slave io_thread;
Query OK, 0 rows affected (0.08 sec)

mysql> 

另一台slave咱们没有中止io线程,因此还在继续接收日志。

(3)模拟sysbench压力测试。

在主库上(192.168.0.50)进行压力测试,持续时间为3分钟,产生大量的binlog。

复制代码
[root@192.168.0.50 ~]# 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=180 --mysql-user=root --mysql-socket=/tmp/mysql.sock --mysql-password=123456 --db-driver=mysql --mysql-table-engine=innodb --oltp-test-mode=complex run 
sysbench 0.4.12:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 16
Initializing random number generator from timer.


Doing OLTP test.
Running mixed OLTP test
Using Uniform distribution
Using "BEGIN" for starting transactions
Using auto_inc on the id column
Threads started!
Time limit exceeded, exiting...
(last message repeated 15 times)
Done.

OLTP test statistics:
    queries performed:
        read:                            15092
        write:                           5390
        other:                           2156
        total:                           22638
    transactions:                        1078   (5.92 per sec.)
    deadlocks:                           0      (0.00 per sec.)
    read/write requests:                 20482  (112.56 per sec.)
    other operations:                    2156   (11.85 per sec.)

Test execution summary:
    total time:                          181.9728s
    total number of events:              1078
    total time taken by event execution: 2910.4518
    per-request statistics:
         min:                                934.29ms
         avg:                               2699.86ms
         max:                               7679.95ms
         approx.  95 percentile:            4441.47ms

Threads fairness:
    events (avg/stddev):           67.3750/1.49
    execution time (avg/stddev):   181.9032/0.11
复制代码

(4)开启slave(192.168.0.60)上的IO线程,追赶落后于master的binlog。

mysql> start slave io_thread;     
Query OK, 0 rows affected (0.00 sec)

mysql> 

(5)杀掉主库mysql进程,模拟主库发生故障,进行自动failover操做。

[root@192.168.0.50 ~]# pkill -9 mysqld

(6)查看MHA切换日志,了解整个切换过程,在192.168.0.20上查看日志:

  View Code

看到最后的Master failover to 192.168.0.60(192.168.0.60:3306) completed successfully.说明备选master如今已经上位了。

从上面的输出能够看出整个MHA的切换过程,共包括如下的步骤:

1.配置文件检查阶段,这个阶段会检查整个集群配置文件配置

2.宕机的master处理,这个阶段包括虚拟ip摘除操做,主机关机操做(这个我这里尚未实现,须要研究)

3.复制dead maste和最新slave相差的relay log,并保存到MHA Manger具体的目录下

4.识别含有最新更新的slave

5.应用从master保存的二进制日志事件(binlog events)

6.提高一个slave为新的master进行复制

7.使其余的slave链接新的master进行复制

最后启动MHA Manger监控,查看集群里面如今谁是master(在切换后监控就中止了。。。还有东西没搞对?)后来在官方网站看到这句话就明白了 。

Running MHA Manager from daemontools

Currently MHA Manager process does not run as a daemon. If failover completed successfully or the master process was killed by accident, the manager stops working. To run as a daemon, daemontool. or any external daemon program can be used. Here is an example to run from daemontools.
[root@192.168.0.20 ~]# masterha_check_status --conf=/etc/masterha/app1.cnf
app1 (pid:23971) is running(0:PING_OK), master:192.168.0.60
[root@192.168.0.20 ~]# 

二.手动Failover(MHA Manager必须没有运行)

手动failover,这种场景意味着在业务上没有启用MHA自动切换功能,当主服务器故障时,人工手动调用MHA来进行故障切换操做,具体命令以下:

注意:若是,MHA manager检测到没有dead的server,将报错,并结束failover: 

Mon Apr 21 21:23:33 2014 - [info] Dead Servers:
Mon Apr 21 21:23:33 2014 - [error][/usr/local/share/perl5/MHA/MasterFailover.pm, ln181] None of server is dead. Stop failover.
Mon Apr 21 21:23:33 2014 - [error][/usr/local/share/perl5/MHA/ManagerUtil.pm, ln178] Got ERROR:  at /usr/local/bin/masterha_master_switch line 53

进行手动切换命令以下:

[root@192.168.0.20 ~]# masterha_master_switch --master_state=dead --conf=/etc/masterha/app1.cnf --dead_master_host=192.168.0.50 --dead_master_port=3306 --new_master_host=192.168.0.60 --new_master_port=3306 --ignore_last_failover

输出的信息会询问你是否进行切换:

  View Code

上述模拟了master宕机的状况下手动把192.168.0.60提高为主库的操做过程。

三.在线进行切换

 在许多状况下, 须要将现有的主服务器迁移到另一台服务器上。 好比主服务器硬件故障,RAID 控制卡须要重建,将主服务器移到性能更好的服务器上等等。维护主服务器引发性能降低, 致使停机时间至少没法写入数据。 另外, 阻塞或杀掉当前运行的会话会致使主主之间数据不一致的问题发生。 MHA 提供快速切换和优雅的阻塞写入,这个切换过程只须要 0.5-2s 的时间,这段时间内数据是没法写入的。在不少状况下,0.5-2s 的阻塞写入是能够接受的。所以切换主服务器不须要计划分配维护时间窗口。

MHA在线切换的大概过程:
1.检测复制设置和肯定当前主服务器
2.肯定新的主服务器
3.阻塞写入到当前主服务器
4.等待全部从服务器遇上复制
5.授予写入到新的主服务器
6.从新设置从服务器 

注意,在线切换的时候应用架构须要考虑如下两个问题:

1.自动识别master和slave的问题(master的机器可能会切换),若是采用了vip的方式,基本能够解决这个问题。

2.负载均衡的问题(能够定义大概的读写比例,每台机器可承担的负载比例,当有机器离开集群时,须要考虑这个问题)

为了保证数据彻底一致性,在最快的时间内完成切换,MHA的在线切换必须知足如下条件才会切换成功,不然会切换失败。

1.全部slave的IO线程都在运行

2.全部slave的SQL线程都在运行

3.全部的show slave status的输出中Seconds_Behind_Master参数小于或者等于running_updates_limit秒,若是在切换过程当中不指定running_updates_limit,那么默认状况下running_updates_limit为1秒。

4.在master端,经过show processlist输出,没有一个更新花费的时间大于running_updates_limit秒。

在线切换步骤以下:

首先,停掉MHA监控:

[root@192.168.0.20 ~]# masterha_stop --conf=/etc/masterha/app1.cnf

其次,进行在线切换操做(模拟在线切换主库操做,原主库192.168.0.50变为slave,192.168.0.60提高为新的主库)

[root@192.168.0.20 ~]# masterha_master_switch --conf=/etc/masterha/app1.cnf --master_state=alive --new_master_host=192.168.0.60 --new_master_port=3306 --orig_master_is_new_slave --running_updates_limit=10000

最后查看日志,了解切换过程,输出信息以下:

  View Code

其中参数的意思:

--orig_master_is_new_slave 切换时加上此参数是将原 master 变为 slave 节点,若是不加此参数,原来的 master 将不启动

--running_updates_limit=10000,故障切换时,候选master 若是有延迟的话, mha 切换不能成功,加上此参数表示延迟在此时间范围内均可切换(单位为s),可是切换的时间长短是由recover 时relay 日志的大小决定 

注意:因为在线进行切换须要调用到master_ip_online_change这个脚本,可是因为该脚本不完整,须要本身进行相应的修改,我google到后发现仍是有问题,脚本中new_master_password这个变量获取不到,致使在线切换失败,因此进行了相关的硬编码,直接把mysql的root用户密码赋值给变量new_master_password,若是有哪位大牛知道缘由,请指点指点。这个脚本还能够管理vip。下面贴出脚本:

  View Code

四.修复宕机的Master 

一般状况下自动切换之后,原master可能已经废弃掉,待原master主机修复后,若是数据完整的状况下,可能想把原来master从新做为新主库的slave,这时咱们能够借助当时自动切换时刻的MHA日志来完成对原master的修复。下面是提取相关日志的命令:

[root@192.168.0.20 app1]# grep -i "All other slaves should start" manager.log 
Mon Apr 21 22:28:33 2014 - [info]  All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='192.168.0.60', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000022', MASTER_LOG_POS=506716, MASTER_USER='repl', MASTER_PASSWORD='xxx';
[root@192.168.0.20 app1]# 

获取上述信息之后,就能够直接在修复后的master上执行change master to相关操做,从新做为从库了。

最后补充一下邮件发送脚本send_report ,这个脚本在询问一位朋友后可使用,以下:

  View Code

最后切换之后发送告警的邮件示例,注意,这个是我后续的测试,和上面环境出现的ip不一致不要在乎。

 

总结:

目前高可用方案能够必定程度上实现数据库的高可用,好比前面文章介绍的MMMheartbeat+drbdCluster等。还有percona的Galera Cluster等。这些高可用软件各有优劣。在进行高可用方案选择时,主要是看业务还有对数据一致性方面的要求。最后出于对数据库的高可用和数据一致性的要求,推荐使用MHA架构。

 

做者:Atlas

出处:Atlas的博客 http://www.cnblogs.com/gomysql

您的支持是对博主最大的鼓励,感谢您的认真阅读。本文版权归做者全部,欢迎转载,但请保留该声明。

相关文章
相关标签/搜索