MHA的存在意义及基本特性
我们都知道MHA是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。在MySQL故障切换过程中,MHA能做到在0~30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。下面是他作为高可用框架的一些基本特性。
参数 | 值 |
---|---|
故障响应时间 | 0 - 30s |
服务器资源的利用率 | 很高,MHA是独立于MySQL集群本身的,只是保证了集群的高可用。不会因为架构的原因导致某个从库单纯的只作为备份而不提供服务。 |
故障切换是否安全 | MHA会在切换过程中尽可能的保证数据的一致性。 |
维护成本和难度 | 是比较成熟且受欢迎的开源高可用框架,所以文档和网上的FAQ案例也相对来说比较完善。 |
二次开发特性 | 可以按需调整故障检测和故障响应的方式,算是比较灵活了吧 |
是否会产生脑裂等现象 | 不会 |
MHA的限制条件
1. 目前MHA主要支持一主多从的架构
- 要搭建MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当master,一台充当备用master,另外一台充当从库,因为至少需要三台服务器,出于机器成本的考虑,淘宝也在该基础上进行了改造,目前淘宝TMHA已经支持一主一从。
- 默认情况下,MHA是不支持3层或多层复制架构的(Master1 -> Master2 -> Slave3), MHA可以恢复Master2,但是不能恢复Slave3,因为Master2,Slave3有不同的master,为了让MHA支持以上架构,可以参考如下配置:
- 在配置文件中,只配置两层(master1 and master2)
- 使用 “multi_tier_slave=1” 参数,然后设置所有hosts
2. MySQL版本必须是5.0 或者高于 5.0
3. 使用mysqlbinlog 5.1+ 支持MySQL5.1+
- MHA使用mysqlbinlog来应用日志到目标slave上的
- 如果MySQL master设置的是row格式,那么MySQL必须是大于等于5.1版本,因为5.0不支持row
- mysqlbinlog版本可以这样被检测:
1 2 3 |
[app@slave_host1]$ mysqlbinlog --version mysqlbinlog Ver 3.3 for unknown-linux-gnu at x86_64 |
- 如果你使用的是MySQL5.1,那么mysqlbinlog必须大于等于3.3
- 如果mysqlbinlog的版本是3.2,而mysql的版本是5.1,那么mha manager会报错,且停止monitoring
4. log-bin必须在候选master上开启
- 如果当前slave没有设置log-bin,那么很显然它不能成为提升为new master
- 如果没有任何机器设置了log-bin,那么mha会报错且停止failover
5. binlog,relay-log 主从环境必须全部一致
- 复制过滤规则(binlog-do-db, replicate-ignore-db 等等)必须全部一致
6. 复制用户必须在候选master上要存在
- 切换完成后,所有slave都必须执行change master 命令。在new master上复制用户必须有(REPLICATEION SLAVE权限)
7. 使用purge_relay_logs来定期删除relay logs
- 默认情况下,如果SQL线程执行完relay-log,relay logs就会被自动删除。但是这些relay-logs 也许还会用来恢复其他的slave,所以你需要关闭自动删除relay-logs的purge线程,然后自己阶段性的来删除如果是你自己来删的话,必须考虑repl 延迟问题,最好让slave删除relay log不要在同一时间点,假如需要恢复,那么这个时间点所有relay logs都被删除了就不好了。
MHA 的基本结构
从架构上来说,MHA分为如下两大部分:
1. Node部分
我们知道,MHA是基于MySQL Replication环境的,在该环境中,不管是Master角色,还是Slave角色,都称为Node,是被监控管理的对象节点。
Node服务器上需要安装MHA Node包。
2. Manager部分
Manager为MHA架构中的管理者,建议部署在一台独立的服务器上,当然也可部署在某个Slave上,但该Slave永远不要被选择成为新的Master,否则故障切换后的MHA架构就失去了高可用性。Manager服务器需要安装MHA Manager包,并完善一个主配置文件。
一个Manager可管理多套MySQL Replication环境(图片摘自网上)。
MHA安装配置
现在我有这样一套基于3306端口的主从复制结构,需要加上MHA的高可用:
IP地址 | 角色 | hostname | server id | 类型 |
---|---|---|---|---|
10.67.250.1 | Master | server1 | 1 | 写 |
10.67.250.2 | slave1 + Manager | server2 | 2 | 只读 |
10.67.250.3 | slave2 (backup) | server3 | 3 | 只读 |
1. 在每台MHA集群服务器上安装依赖
1 |
$ yum install -y perl-DBD-MySQL |
2. 在每台机器上安装MHA Node软件包
推荐使用rpm的方式安装:
1 2 3 |
$ curl http://www.mysql.gr.jp/frame/modules/bwiki/index.php\?plugin\=attach\&pcmd\=open\&file\=mha4mysql-manager-0.56-0.el6.noarch.rpm\&refer\=matsunobu -o mha4mysql-manager-0.56-0.el6.noarch.rpm $ yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm |
也可以选择源码安装:
1 2 3 4 5 |
wget http://mysql-master-ha.googlecode.com/files/mha4mysql-node-0.56.tar.gz tar xf mha4mysql-node-0.56.tar.gz cd mha4mysql-node-0.56 perl Makefile.PL make && make install |
Node工具包(这些工具通常由MHA Manager的脚本触发,无需人为操作)主要包括以下几个工具:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$ rpm -ql mha4mysql-node-0.56-0.el6.noarch /usr/bin/apply_diff_relay_logs # 识别差异的中继日志事件并将其差异的事件应用于其他的slave /usr/bin/filter_mysqlbinlog # 去除不必要的ROLLBACK事件(MHA已不再使用这个工具) /usr/bin/purge_relay_logs # 清除中继日志(不会阻塞SQL线程) /usr/bin/save_binary_logs # 保存和复制master的二进制日志 /usr/share/man/man1/apply_diff_relay_logs.1.gz /usr/share/man/man1/filter_mysqlbinlog.1.gz /usr/share/man/man1/purge_relay_logs.1.gz /usr/share/man/man1/save_binary_logs.1.gz /usr/share/perl5/vendor_perl/MHA/BinlogHeaderParser.pm /usr/share/perl5/vendor_perl/MHA/BinlogManager.pm /usr/share/perl5/vendor_perl/MHA/BinlogPosFindManager.pm /usr/share/perl5/vendor_perl/MHA/BinlogPosFinder.pm /usr/share/perl5/vendor_perl/MHA/BinlogPosFinderElp.pm /usr/share/perl5/vendor_perl/MHA/BinlogPosFinderXid.pm /usr/share/perl5/vendor_perl/MHA/NodeConst.pm /usr/share/perl5/vendor_perl/MHA/NodeUtil.pm /usr/share/perl5/vendor_perl/MHA/SlaveUtil.pm |
3. 安装MHA Manager
推荐使用rpm的安装方式:
1 2 3 |
$ curl http://www.mysql.gr.jp/frame/modules/bwiki/index.php\?plugin\=attach\&pcmd\=open\&file\=mha4mysql-manager-0.56-0.el6.noarch.rpm\&refer\=matsunobu -o mha4mysql-manager-0.56-0.el6.noarch.rpm $ yum localinstall -y mha4mysql-manager-0.56-0.el6.noarch.rpm |
也可以使用源码方式安装:
1 2 3 4 5 |
wget http://mysql-master-ha.googlecode.com/files/mha4mysql-manager-0.56.tar.gz tar xf mha4mysql-manager-0.56.tar.gz cd mha4mysql-manager-0.56 perl Makefile.PL make && make install |
Manager工具包主要包括以下几个工具:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# rpm -ql mha4mysql-manager-0.56-0.el6.noarch /usr/bin/masterha_check_repl # 检查MHA作用集群的主从复制 /usr/bin/masterha_check_ssh # 检查MHA作用集群的SSH连通性 /usr/bin/masterha_check_status # 检查MHA Manager的状态 /usr/bin/masterha_conf_host # 添加过删除配置的server信息 /usr/bin/masterha_manager # 启动MHA Manager /usr/bin/masterha_master_monitor # 检测MySQL是否宕机 /usr/bin/masterha_master_switch # 手动触发MHA的切换 /usr/bin/masterha_secondary_check # 用于故障产生时的二次检测 /usr/bin/masterha_stop # 关闭MHA Manager /usr/share/man/man1/masterha_check_repl.1.gz /usr/share/man/man1/masterha_check_ssh.1.gz /usr/share/man/man1/masterha_check_status.1.gz /usr/share/man/man1/masterha_conf_host.1.gz /usr/share/man/man1/masterha_manager.1.gz /usr/share/man/man1/masterha_master_monitor.1.gz /usr/share/man/man1/masterha_master_switch.1.gz /usr/share/man/man1/masterha_secondary_check.1.gz /usr/share/man/man1/masterha_stop.1.gz /usr/share/perl5/vendor_perl/MHA/Config.pm /usr/share/perl5/vendor_perl/MHA/DBHelper.pm /usr/share/perl5/vendor_perl/MHA/FileStatus.pm /usr/share/perl5/vendor_perl/MHA/HealthCheck.pm /usr/share/perl5/vendor_perl/MHA/ManagerAdmin.pm /usr/share/perl5/vendor_perl/MHA/ManagerAdminWrapper.pm /usr/share/perl5/vendor_perl/MHA/ManagerConst.pm /usr/share/perl5/vendor_perl/MHA/ManagerUtil.pm /usr/share/perl5/vendor_perl/MHA/MasterFailover.pm /usr/share/perl5/vendor_perl/MHA/MasterMonitor.pm /usr/share/perl5/vendor_perl/MHA/MasterRotate.pm /usr/share/perl5/vendor_perl/MHA/SSHCheck.pm /usr/share/perl5/vendor_perl/MHA/Server.pm /usr/share/perl5/vendor_perl/MHA/ServerManager.pm |
如果你采用的是源码安装,那么安装完Manager后在安装目录底下存在一个 sample/scripts 目录,里面存在了一些功能性脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ ll mha4mysql-manager-0.56/samples/scripts 总用量 32 -rwxr-xr-x. 1 4984 users 3648 4月 1 2014 master_ip_failover -rwxr-xr-x. 1 4984 users 9870 4月 1 2014 master_ip_online_change -rwxr-xr-x. 1 4984 users 11867 4月 1 2014 power_manager -rwxr-xr-x. 1 4984 users 1360 4月 1 2014 send_report 上面的这几个脚本都不是必须的,可根据自己的业务需求决定是否使用和调整。 master_ip_failover # 是自动切换时vip管理的脚本,不是必须,如果我们使用keepalived的,我们可以自己编写脚本完成对vip的管理,比如监控mysql,如果mysql异常,我们停止keepalived就行,这样vip就会自动漂移. master_ip_online_change # 在线切换时vip的管理,不是必须,同样可以可以自行编写简单的shell完成. power_manager # 故障发生后关闭主机的脚本,不是必须. send_report # 因故障切换后发送报警的脚本,不是必须,可自行编写简单的shell完成. |
4. 配置前的准备工作
首先需要做一些配置之前的准备工作:
4.1 两台slave服务器设置read_only
1 2 |
set global read_only = ON; set global relay_log_purge = 0 ; |
4.2 创建监控用户,用于MHA Manager管理其他数据库node节点
1 2 |
grant all on *.* to "mha_user"@"10.67.250.%" identified by "xxxxxx"; flush privileges; |
4.3 实现三台服务器之间的SSH免密码登录
详情可参考 http://www.foreverlakers.com/tag/ssh/
注: 这里要注意,如果我们配置免密码登录的用户不是root用户(比如是mhatest用户),那么需要注意以下几点:
1. 将Manager的配置文件中指定的 manager_workdir 目录的权限修改为免密码登录认证的用户权限。比如,我们在配置文件中写到: manager_workdir = /usr/local/mha , 那么一定要确保
chown -R mhatest:mhatest /usr/local/mha
2. 将Manager的配置文件中指定的remote_workdir 目录也在对应的node节点将权限改为免密码登录认证的用户权限,比如,我们在配置文件中写道: remote_workdir = /home/data/mha, 那么一定要确保
chown -R meatiest:mhatest /home/data/mha
5. 配置MHA Manager
5.1 配置MHA的Manager
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
$ mkdir -p /usr/local/mha $ vim /etc/mha.cnf [server default] manager_workdir = /usr/local/mha // MHA Manager的工作目录 manager_log = /usr/local/mha/manager.log // MHA Manager的log文件 master_binlog_dir = /home/data/mysql // master 保存binlog的位置,以便MHA可以找到master的日志 #master_ip_failover_script = /usr/local/bin/master_ip_failover // failover时候的切换ip的脚本,如果运用了keepalived等虚IP保证高可用的话可以加上, 如果你是源码安装则此默认存在与安装目录的sample目录下,rpm包安装则没有。 user = mha_user // MHA Manager来进行管理控制MySQL的用户名 password = xxxxx // MHA Manager来进行管理控制MySQL对应的密码 ping_interval = 3 // 监控主库,发送ping包的时间间隔,默认是3秒,尝试三次没有回应的时候自动进行failover remote_workdir = /home/data/mha // 远端mysql在发生切换时binlog的保存位置, repl_user = replicauser // 复制用户的用户名 repl_password = xxxx // 复制用户的密码 report_script = /usr/local/bin/send_report //切换后发送报警的脚本,可以自己定义 secondary_check_script = /usr/bin/masterha_secondary_check -s 10.67.250.2 -s 10.67.250.3 --user=mha_test --port=4344 --master_host=10.3.250.88 --master_ip=10.3.250.88 --master_port=3306 --master_user=mha_user --master_password="xxxxxx" --ping_type=SELECT // 二次检测的脚本,当发生故障后会通过次脚本检测从指定host到主库的连通性来判断主库是否真的宕机了,降低误切换的可能性 shutdown_script = "" // 故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机放在发生脑裂,这里没有使用) ssh_user = mha_test // ssh的登录用户名 ssh_port = 4311 // ssh的登录端口号 [server1] hostname = 10.67.250.1 port = 3306 [server2] hostname = 10.67.250.2 port = 3306 [server3] hostname = 10.67.250.3 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 |
5.2 配置检查
1 2 |
$ masterha_check_ssh --conf=/etc/mha.cnf //检查ssh链接是否OK $ masterha_check_repl --conf=/etc/mha.cnf //检查主从复制是否OK |
5.3 通过master_check_status脚本查看Manager的状态
1 2 3 |
$ masterha_check_status --conf=/etc/mha.cnf //如果正常,会显示"PING_OK",否则会显示"NOT_RUNNING",这代表MHA监控没有开启。 mha is stopped(2:NOT_RUNNING). |
5.4 启动MHA Manager 即可正常运行
1 |
$ nohup masterha_manager --conf=/etc/mha.cnf --ignore_last_failover < /dev/null > /usr/local/mha/manager.log 2>&1 & |
5.5 再次check MHA 的Manager 是否启动成功
1 2 |
$ masterha_check_status --conf=/usr/local/mha/mha.cnf mha (pid:29299) is running(0:PING_OK), master:10.67.250.1 |
6. MHA 功能分离实现
6.1 自己监控,调用mha进行切换
有时候,我们可能因为各种原因不想让MHA承担监控和切换的全部工作。 或许是因为不相信它,或许是因为特殊的业务逻辑,那么如果我们想自己来监控数据库的可用性,而在我们自己确定数据库故障时,用MHA作为主从切换的 工具呢 ?
其实也很简单,在上面安装完MHA 的 Manager节点完后,会有一个masterha_master_switch 脚本,他就是MHA本身的切换脚本,所以完全可以调用他来实现手动的数据库切换。
我们直接打开这个脚本就可以看到:
······省略部分·······
# For master failover // 当master宕机时,可以用下面类似的形式调用
masterha_master_switch –master_state=dead –global_conf=/etc/masterha_default.cnf –conf=/usr/local/masterha/conf/app1.cnf –dead_master_host=host1
# For online master switch //当master在线切换时,可以用下面类似的参数
masterha_master_switch –master_state=alive –global_conf=/etc/masterha_default.cnf –conf=/usr/local/masterha/conf/app1.cnf
See online reference (http://code.google.com/p/mysql-master-ha/wiki/masterha_master_switch) for details.
=head1 DESCRIPTION
See online reference (http://code.google.com/p/mysql-master-ha/wiki/masterha_master_switch) for details.
6.2 自己设置主从切换时的逻辑
如果我在故障发生时,由于业务架构的原因,不想让MHA按照既定的原则切换Master,而是按照我们自己的设定进行故障处理该怎么做呢 ?
在上面安装完MHA 的 Manager节点完后,会有一个 master_ip_failover , 我们根据自己的需求将此脚本更新为我们想要的操作即可。 这里举个例子,如果我们的数据库复制群是建立在Atlas为proxy的基础之上的话,我们想要做到在主库宕机后,在proxy里自动下掉,或者在主库发生故障时将主库的Keepalive停掉,使得虚拟IP被切换到备库上去,我们就可以在此脚本中加上一些操作满足我们的需求。
至此,MHA的简单原理和部署已经告一段落,后续我会专门再总结一下MHA高可用性能的测试:
http://www.foreverlakers.com/2017/05/mysql-mha原理(二)/