秒级故障切换!用MHA轻松实现MySQL高可用(三)

郝朝阳 2016-08-24 10:14:53

作者介绍  

郝朝阳运维工程师,专注于运维自动化的实现。现就职于宜搜科技,负责前端运维工作。虽然多方面开花,却致力于形成自己运维体系思想。

 

在上一篇的MHA介绍中提及过其它一些MySQL的高可用解决方案,只是略微介绍了以下,在这里详细地介绍。

 

MySQL复制是异步或者半同步的。当master故障时,一些slave可能并没有收到最新的relay log,也就意味着每个slave可能处于不同的状态。手动处理这些一致性问题是小事,因为不修复这些问题,就不能开始复制。但是手动修复这些问题,花费一个小时或更多的时间并不少见。

 

一主一从
 

 

如果架构是一主一从,就不会出现一部分slave的状态落后于最新的slave的问题。当master出现故障,可以将应用的流量全部发送给新的master(原来的slave)。故障切换很容易解决。但是会有下面的问题。

 

首先,不能扩展读流量。在很多情况下,可能会运行一些重要的操作,比如备份、分析查询、批量处理。这可能会导致slave的性能问题。如果只要一个slave,当这个slave出现故障后,master必须处理所有这些流量。

 

其次,可用性问题。如果master出现故障,只剩下一台服务(原来的slave成为主),就成为了单点故障问题。为了创建一个新的slave,需要在线备份,然后存储到新的slave上并立即启动slave。但是这些操作通常会花费数小时(甚至是不止一天才能完成复制)。在一些重要的应用上,可能忍受不了数据库这么长时间有单点故障问题。并且,在线备份会大大增加master的I/O负载,因此在高峰期进行备份是很危险的。

 

双主多从
 

 

双主多从也是常见的架构。如果当前的master出现故障,备用的master就会变为新master。大很多场景下,备用的master都配置为只读。

 

但这不总是作为master故障切换解决方案运行的。当目前的master出现故障,余下的slave可能没有接收到全部的relay log,因此在slave之间解决一致性问题仍需要其它解决方案。

 

如果不能忍受一致性问题并且还想立即启动服务。只需要将备用的master作为新的master,并且抛弃剩余的slave。之后再从这个新的master做线上备份创建新的slave。但是这个方法和前面提到的一主一从的发法有同样的问题。剩余的slave不能进行读扩展和进行冗余的目的。

 

另外,使用双主(一个只读)并且每个master都至少有一个从也是可能的。

 

至少一个从可以进行复制,如果目前的master出现故障。但是事实上,很多使用者都不会采用这种架构,因为最大的缺点是复杂性。在这种架构中使用了三层复制。管理三层复制并不容易。例如,如果备用master出现故障,备用master的slave就无法继续进行复制。很多情况下,必须重新配置备用master和它的slave。重要的是,在这种架构中,必须要使用至少4台服务器。

 

心跳+DRBD
 

 

使用心跳(Heartbeat)+DRBD+MySQL是非常常见的HA解决方案。但是这个解决方案有一些严重的问题。

 

第一个问题是开销,特别是想运行大量MySQL复制环境的时候。心跳+DRBD是主用/备用解决方案,因此需要一个不处理任何应用流量的被动(standby)master。被动服务器不能被用来进行读扩展。通常,你至少需要4台MySQL服务,一个主动(active)master,一个被动(passive)master,两个slave。

 

第二个问题是停机。因为心跳+Heartbeat是active/standby集群,因此如果active server出现故障,故障恢复会发生在passive server上。这可能需要花费很长的时间,特别是没有用InnoDB插件。即使使用了InnoDB插件,只花费几分钟在passive server开始接收访问连接的情况并不常见。除了故障恢复时间,在故障恢复后,热身(warm-up)(填充数据到缓冲池)也要花费时间,因为在passive上,数据库/文件系统缓存是空的。在实际中,需要一个或更多额外的slave来处理足够的读流量。在warm-up期间,由于还粗是空的,因此写性能会显著下降。

 

第三个问题是写性能下降或一致性问题。为了保证active/passive高可用集群运行,在每次commit必须把事务日志(二进制日志和InnoDB日志)刷新到磁盘,因此必须设置innodb-flush-log-at-trx-cmmit=1和sync-binlog=1。但是sync-binlog=1会降低写性能,因为在当前的MySQL版本fsync()是连续的(如果sync-binlog是1,组提交就会打破)。大多数情况下,不会设置sync-binlog=1。但是如果sync-binlog=1没有设置,当active master故障,新的master(之前的passive server)可能会丢失已经被发送到slave上的二进制日志事件。假如,master出现故障,并且slave A接收到mysql-bin.00123的1500位置。如果binlog数据近刷新到1000位置到磁盘,新的master仅只有mysql-bin.00123到1000位置并且创建新的二进制文件mysql-bin.00124。如果出现这种情况,由于新的master没有mysql-bin.00123的1500位置,slave A就不能进行复制了。

 

第四个问题是复杂性。对于很多用户来说,安装/配置心跳和DRBD是不简单的。在很多部署环境,配置DRBD经常需要重建系统分区,这在很多情况下是不容易的。另外,也需要在DRBD和Linux内核层有足够的经验。如果执行了一个错误的命令(比如在passive节点执行了drbd –overwrite-data-of-peer)非常容易损坏生产数据。当使用DRBD,一旦出现磁盘I/O层的问题,对于大多数DBA来说,解决这个问题是很难的。

 

MySQL集群
 

 

MySQL集群真正实现了高可用解决方案,但是必须使用NDB存储引擎。大多数情况下都是使用InnoDB,因此无法使用MySQL集群的优势。

 

  • 半同步复制

 

半同步复制大大降低了”binlog仅存在故障master上”的风险。这对避免数据的丢失有很大的帮助。但是半同步复制并没有解决一致性问题。半同步复制保证在master提交时至少有一个(并不是所有)slave接收到binlog事件。仍有可能一些slave没有接收到binlog事件。如果没有将最新的slave上的relay log应用到非最新的slave上,slave就无法处于一致性状态。

 

MHA解决了一致性问题,因此通过将半同步复制和MHA一起使用,几乎没有数据丢失和slave保持一直就能实现。

 

全局事务ID(GTID)
 

 

全局事务ID的目的和MHA想要实现的是基本相同的,但是全局事务ID包括的更多。MHA只能支持两层复制,但是全局事务ID可以支持很多层复制的环境,因此即使第二层复制故障了,仍然可以恢复三层复制。

 

从MySQL5.6开始就开始支持GTID了。Oracle的官方工具mysqlfailover支持带GTID的master故障切换。从MHA的0.56版本开始,也支持基于GTID的故障切换。MHA会自动检测mysqld是否在GTID运行,如果GTID开启,MHA就实现带GTID的故障切换,如果没有启用,MHA就使用基于relay log的故障切换。

 

往期回顾:

秒级故障切换!用MHA轻松实现MySQL高可用(一)

秒级故障切换!用MHA轻松实现MySQL高可用(二)

 

 
 
精选专题(点击蓝色标题可阅读全文)

 

◆  近期热文  ◆  

 

MaxScale:实现MySQL读写分离与负载均衡的中间件利器

腾讯高级工程师:一道面试题引发的高并发性能调试思考

【推荐】一款足以秒杀流行商业数据库的异域猛禽

10年研发老兵:如何构建适合自己的DevOps工具与平台

浙江移动亿万级实时流计算之路与踩过的坑

 

◆  专家专栏  ◆  

杨志洪杨建荣陈能技丁俊卢钧轶李海翔

魏兴华邹德裕周正中高强白鳝卢飞王佩

 

◆  近期活动  ◆  

Gdevops全球敏捷运维峰会广州站


峰会官网:www.gdevops.com

活动预告