基于MHA方式实现MySQL的高可用


MHA是由日本Mysql专家用Perl写的一套Mysql故障切换方案以保障数据库的高可用性,它的功能是能在0-30s之内实现主Mysql故障转移(failover),MHA故障转移可以很好的帮我们解决从库数据的一致性问题,同时最大化挽回故障发生后的数据。MHA里有两个角色一个是node节点 一个是manager节点,要实现这个MHA,必须最少要三台数据库服务器,一主多备,即一台充当master,一台充当master的备份机,另外一台是从属机,这里实验为了实现更好的效果使用三台机器,需要说明的是一旦主服务器宕机,备份机即开始充当master提供服务,如果主服务器上线也不会再成为master了,因为如果这样数据库的一致性就被改变了。


MHA监控复制架构的主服务器,一旦检测到主服务器故障,就会自动进行故障转移。即使有些从服务器没有收到最新的relay log,MHA自动从最新的从服务器上识别差异的relay log并把这些日志应用到其他从服务器上,因此所有的从服务器保持一致性了。MHA通常在几秒内完成故障转移,9-12秒可以检测出主服务器故障,7-10秒内关闭故障的主服务器以避免脑裂,几秒中内应用差异的relay log到新的主服务器上,整个过程可以在10-30s内完成。还可以设置优先级指定其中的一台slave作为master的候选人。由于MHA在slaves之间修复一致性,因此可以将任何slave变成新的master,而不会发生一致性的问题,从而导致复制失败。


Advantages of MHA

1 Masterfailover and slave promotion can be done very quickly

自动故障转移快

2 Mastercrash does not result in data inconsistency

主库崩溃不存在数据一致性问题

3 Noneed to modify current MySQL settings (MHA works with regular MySQL (5.0 orlater))

不需要对当前mysql环境做重大修改

4 Noneed to increase lots of servers

不需要添加额外的服务器(仅一台manager就可管理上百个replication)

5 Noperformance penalty

性能优秀,可工作在半同步复制和异步复制,当监控mysql状态时,仅需要每隔N秒向master发送ping包(默认3秒),所以对性能无影响。你可以理解为MHA的性能和简单的主从复制框架性能一样。

6 Works with any storage engine

只要replication支持的存储引擎,MHA都支持,不会局限于innodb


Requirements and Limitations


1 这一部分做简要翻译,安装MHA的依赖和限制

2 SSH public key认证

3 仅支持Liunx操作系统

4 只有一台master能被设置成readonly=0,其他设置为只读

5如果是Master1 -> Master2-> Slave3这样的三级复制框架,在配置文件中只需要设置master1和master2这样的二级复制结构,并设置multi_tier_slave=1来支持三级复制结构。

6 MHA仅支持mysql 5.0及以后的版本

7 mysqlbinlog必须是3.3及以上版本

8 log-bin必须在每一个可成为master的mysql服务器上设置

9 所有mysql服务器的复制过滤规则必须一致

10 必须在能成为master的服务器上设置复制账户

11所有Mysql服务器上必须设置relay_log_purge=1,使得能够保存一段时间的relay log

12 基于语句的复制时,不要使用load datainfile命令


集群节点角色模式:

1、一主多从,任意从都可能成为主库

2、一主多从,其中一个从永远不会成为主库,配置成远程数据中心

3、一主多从,配置一个候选主节点



实验环境:

Centos6.5

10.100.10.104 master  mysql主库

10.100.10.105 backup 从库中的备用主库

10.100.10.106 slave 从库

10.100.10.200   VIP

实验步骤:

1、分别在3台服务修改hostname,主机名自己定

[root@localhost ~]# vi /etc/sysconfig/network

HOSTNAME=master


2、配置ssh公钥免登录环境

分别在3台服务器上执行

ssh-keygen -t rsa -P ''

ssh-copy-id -i /root/.ssh/id_rsa.pub root@10.100.10.105

ssh-copy-id -i /root/.ssh/id_rsa.pub root@10.100.10.106


3、关闭selinux和配置IP地址和本地yum源

setenforce 0


4、分别在3台服务器配置epel源

wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm 

rpm -ivh epel-release-6-8.noarch.rpm 

sed-i'/#baseurl=/s/#base/base/g'/etc/yum.repos.d/epel.repo

sed-i'/mirrorlist=/s/^/#/g'/etc/yum.repos.d/epel.repo


5、分别在3台服务器配置hosts文件

[root@localhost ~]# vi /etc/hosts

10.100.10.104  master

10.100.10.105  backup

10.100.10.106  slave


6、安装mysql5.6配置Mysql的主从同步关系并通过grant命令赋权

a、所有mysql数据库服务器安装半同步插件(semisync_master.so,semisync_slave.so) 

mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';      

mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so'; 

b、编辑my.cnf

[mysqld]

port            = 3306

socket          = /tmp/mysql.sock

skip-external-locking

log-bin = mysql-bin

要求所有可能成为主库的节点开启二进制日志,反面来说不能成为主库的从库不开启二进制日志可以增强服务性能

log-bin-index = binlog_index

relay_log_purge = 0

要求所有可能成为主库的节点配置 relay_log_purge = 0

read_only = 1

MHA要求所有slave节点配置为read_only = 1

relay_log = /usr/local/mysql/data/relay-bin

relay_log_index = /usr/local/mysql/data/relay-bin.index

server-id       = 2

注意主从节点的server-id 不同

rpl_semi_sync_master_enabled=1

rpl_semi_sync_master_timeout=1000

rpl_semi_sync_slave_enabled=1

开启半同步模式为保证数据的完整性,mysql半同步指只要有一台从库返回了主库的二进制更新,主库便认为集群主从同步完成

c、配置主从同步

在主服务器及可能成为主库的从库上执行

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

flush privileges;

在每台服务器上执行

mysql>grant all privileges on *.* to 'root'@'`uname -n`' identified by '123'

这里指定`uname -n`是为了数据库的安全,执行这条赋值权限是因为数据库在切换的时候可能需要执行STOP SLAVE, CHANGE MASTER, RESET SLAVE等

这两个用户在mha配置文件中会用到


7、三个节点安装node包

a、安装依赖包

yum  -y install perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-Config-IniFiles  ncftp perl-Params-Validate  perl-CPAN perl-Test-Mock-LWP.noarch perl-LWP-Authen-Negotiate.noarch perl-devel

b、安装node

tar -zxvf mha4mysql-node-0.53.tar.gz

cd mha4mysql-node-0.53

perl Makefile.PL

make && make install



8、在管理机安装manager包

a、安装依赖包

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

yum install -y perl-devel perl-CPAN

b、安装manager

tar -zxvf mha4mysql-manager-0.53.tar.gz

cd mha4mysql-manager-0.53

perl Makefile.PL

make && make install


mkdir /etc/masterha

mkdir -p /scripts

cp samples/conf/* /etc/masterha/

cp samples/scripts/*  /script


9、编辑主配置文件

mha_manager 有两类配置文件


masterha_default.cnf

mha全局配置文件,可以简化集群下每个节点的配置如果节点有共同的配置


app1.cnf mha可管理多套集群,此为一套

[server default]

user=root 定义登录mysql的用户,给定了all privileges 权限

password=123 root密码

ssh_user=root ssh密码

repl_user=kyo slave复制用户

repl_password=123 slave复制用户密码

上面的这些用户信息都可以特别指定,这里将server1\2\3的信息设置相同故而在[server default]中指定


manager_workdir=/masterha/app1   manager工作目录,服务启动会自动创建

manager_log=/masterha/app1/manager.log manager日志


[server1]

hostname=10.100.10.104 指定集群节点ip

master_binlog_dir=/usr/local/mysql/data 数据库二进制日志位置

candidate_master=1 此参数决定从库成为主库的优先级


[server2]

hostname=10.100.10.105

master_binlog_dir=/usr/local/mysql/data

candidate_master=1

 

[server3]

hostname=10.100.10.106

master_binlog_dir=/usr/local/mysql/data

candidate_master=1

no_master=1 此参数为1表示从库永远不会成为主库



10、测试及排错

(1) 测试过程中需要注意的几个问题:

a、切换过程会自动把read_only关闭

b、切换之后需要删除手工删除/masterha/app1/app1.failover.complete,才能进行第二次测试

c、一旦发生切换管理进程将会退出,无法进行再次测试,需将故障数据库加入到MHA环境中来

d、原主节点重新加入到MHA时只能设置为slave,在

change master to MASTER_HOST='10.100.10.105', MASTER_USER='replicationuser',MASTER_PASSWORD='replicationuser',MASTER_LOG_FILE='mysql-bin.000004',MASTER_LOG_POS=106;

之前需要先 reset slave

e、关于ip地址的接管有几种方式,这里采用的是MHA自动调用ip别名的方式,好处是在能够保证数据库状态与业务Ip 切换的一致性。启动管理节点之后 vip会自动别名到当前主节点上,keepalived也只能做到对3306的健康检查,但是做不到比如像MySQL复制中的slave-SQL、slave-IO进程的检查,容易出现对切换的误判。

f、注意:二级从服务器需要将log_slave_updates打开

g、手工切换需要先定义好master_ip_online_change_script脚本,不然只会切换mysql,Ip地址不会绑定上去,可以根据模板来配置该脚本


(2) 测试主从复制,报错处理

[root@slave]# masterha_check_repl --conf=/etc/masterha/app1.cnf  

Can't exec "mysqlbinlog": 没有那个文件或目录 at /usr/local/share/perl5/MHA/BinlogManager.pm line 99

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

    Testing mysql connection and privileges..sh: mysql: command not found mysql command failed with rc 127:0!

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


正确输出最后内容:

Thu Jul 23 16:48:06 2015 - [info] Slaves settings check done.

Thu Jul 23 16:48:06 2015 - [info] 

10.100.10.105 (current master)

 +--10.100.10.104

 +--10.100.10.106


Thu Jul 23 16:48:06 2015 - [info] Checking replication health on 10.100.10.104..

Thu Jul 23 16:48:06 2015 - [info]  ok.

Thu Jul 23 16:48:06 2015 - [info] Checking replication health on 10.100.10.106..

Thu Jul 23 16:48:06 2015 - [info]  ok.

Thu Jul 23 16:48:06 2015 - [warning] master_ip_failover_script is not defined.

Thu Jul 23 16:48:06 2015 - [warning] shutdown_script is not defined.

Thu Jul 23 16:48:06 2015 - [info] Got exit code 0 (Not master dead).


MySQL Replication Health is OK.


(3) 测试ssh互访

[root@slave masterha]# masterha_check_ssh --conf=/etc/masterha/app1.cnf  

正确输出内容:

Thu Jul 23 16:50:40 2015 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.

Thu Jul 23 16:50:40 2015 - [info] Reading application default configurations from /etc/masterha/app1.cnf..

Thu Jul 23 16:50:40 2015 - [info] Reading server configurations from /etc/masterha/app1.cnf..

Thu Jul 23 16:50:40 2015 - [info] Starting SSH connection tests..

Thu Jul 23 16:50:42 2015 - [debug] 

Thu Jul 23 16:50:40 2015 - [debug]  Connecting via SSH from root@10.100.10.105(10.100.10.105:22) to root@10.100.10.104(10.100.10.104:22)..

Thu Jul 23 16:50:41 2015 - [debug]   ok.

Thu Jul 23 16:50:41 2015 - [debug]  Connecting via SSH from root@10.100.10.105(10.100.10.105:22) to root@10.100.10.106(10.100.10.106:22)..

Thu Jul 23 16:50:42 2015 - [debug]   ok.

Thu Jul 23 16:50:42 2015 - [debug] 

Thu Jul 23 16:50:40 2015 - [debug]  Connecting via SSH from root@10.100.10.104(10.100.10.104:22) to root@10.100.10.105(10.100.10.105:22)..

Thu Jul 23 16:50:41 2015 - [debug]   ok.

Thu Jul 23 16:50:41 2015 - [debug]  Connecting via SSH from root@10.100.10.104(10.100.10.104:22) to root@10.100.10.106(10.100.10.106:22)..

Thu Jul 23 16:50:42 2015 - [debug]   ok.

Thu Jul 23 16:50:43 2015 - [debug] 

Thu Jul 23 16:50:41 2015 - [debug]  Connecting via SSH from root@10.100.10.106(10.100.10.106:22) to root@10.100.10.105(10.100.10.105:22)..

Thu Jul 23 16:50:42 2015 - [debug]   ok.

Thu Jul 23 16:50:42 2015 - [debug]  Connecting via SSH from root@10.100.10.106(10.100.10.106:22) to root@10.100.10.104(10.100.10.104:22)..

Thu Jul 23 16:50:43 2015 - [debug]   ok.

Thu Jul 23 16:50:43 2015 - [info] All SSH connection tests passed successfully.



11、MHA的常用命令:

manager部分

a、检查ssh连接

master_check_ssh --conf=/etc/masterha/app1.conf

b、检查replication

master_check_repl --conf=/etc/masterha/app1.conf

c、开启Manager,可以放在后台执行

master_manager --conf=/etc/masterha/app1.conf

nohup master_manager --conf=/etc/masterha/app1.conf &> /dev/null & 

d、检查MHA manager运行状态

master_check_status --conf=/etc/masterha/app1.conf

e、终止manager

masterha_stop --conf=/etc/masterha/app1.conf

如果无法停止可以尝试加 --abort参数

f、在配置文件中添加或删除host

masterha_conf_host --command=add --conf=/etc/masterha/app1.cnf --hostname=10.100.10.107 --block=server4 --params="no_master=1;ignore_fail=1"

masterha_conf_host --command=delete --conf=/etc/masterha/app1.cnf --hostname=10.100.10.107 --block=server4 --params="no_master=1;ignore_fail=1"

g、删除旧的relay log

 0 5 * * * a /usr/bin/purge_relay_logs --user=root --password=PASSWORD --disable_relay_log_purge >> /var/log/masterha/purge_relay_logs.log 2>&1

h、管理多套集群环境,配置文件创建

masterha_manager --conf=/etc/masterha/app1.conf

masterha_manager --conf=/etc/masterha/app2.conf


Node节点部分:

save_binary_logs:复制master的二进制日志

 $ save_binary_logs --command=test --binlog_dir=/var/lib/mysql

    --start_file=mysqld-bin.000002


    # Saving binary logs


    $ save_binary_logs --command=save --binlog_dir=/var/lib/mysql

    --start_file=mysqld-bin.000002 --start_pos=312

    --output_file=/var/tmp/aggregate.binlog


    # Saving relay logs


    $ save_binary_logs --command=save --start_file=mysqld-relay-bin.000002

    --start_pos=312 --relay_log_info=/var/lib/mysql/relay-log.info

    --output_file=/var/tmp/aggregate.binlog


Apply_diff_relay_logs:从数据最新的slave上产生不同的relay log,并且将其应用到不同的binlog events中

Purge_relay_log:清除relay log


12、管理master ip 地址

a、HA方案,通过keepalive来实现vip转移

b、mha自己提供的master_ip_failover_script故障转移脚本


13、mysql半同步复制配置使用