分布式数据存储 - MySQL主从复制高可用方案

时间:2023-01-31 07:38:17

前面几篇文章说道MySQL数据库的高可用方案主从复制、主从复制的延迟产生原因、延迟检测及延迟解决方案(并未从根本上解决),这种主从复制方案保证数据的冗余的同时可以做读写分离来分担系统压力但是并非是高可用方案,因为主从节点中主节点仍然是单点的,一旦主节点宕机会导致应用中写失败。双主复制虽然很好的避免主节点的单点故障,但是未提供统一访问入口来实现负载均衡,如果其中master宕掉的话需要手动切换到另外一个master,而不能自动进行切换。本篇文章就来剖析主从复制的高可用。

一、基础概念介绍

  • Keepalived/heartbeat

是一个基于VRRP(虚拟路由冗余协议)可用来实现服务高可用性的软件方案,避免出现单点故障。Keepalived一般用来实现轻量级高可用性,且不需要共享存储,一般用于两个节点之间,常见有LVS+Keepalived、Nginx+Keepalived组合。

  • MHA/MMM

MHA是一套MySQL故障切换方案,来保证数据库系统的高可用。在宕机的时间内(通常10—30秒内),完成故障切换,部署MHA,可避免主从一致性问题,易安装,不改变现有部署。 还支持在线切换,从当前运行master切换到一个新的master上面,只需要很短的时间(0.5-2秒内),此时仅仅阻塞写操作,并不影响读操作,便于主机硬件维护。 在有高可用,数据一致性要求的系统上,MHA 提供了有用的功能,几乎无间断的满足维护需要。

  • LVS

(Linux Virtual Server)是一个高可用性虚拟的服务器集群系统。其主要用于多服务器的负载均衡,作用于网络层。LVS构建的服务器集群系统中,前端的负载均衡层被称为Director Server;后端提供服务的服务器组层被称为Real Server。

LVS有三种工作模式,分别是DR(Direct Routing 直接路由)、TUN(Tunneling IP隧道)、NAT(Network Address Translation 网络地址转换)。其中TUN模式能够支持更多的Real Server,但需要所有服务器支持IP隧道协议;DR也可以支持相当的Real Server,但需要保证Director Server虚拟网卡与物理网卡在同一网段;NAT扩展性有限,无法支持更多的Real Server,因为所有的请求包和应答包都需要Director Server进行解析再生,影响效率。 同时,LVS负载均衡有10中调度算法,分别是rr、wrr、lc、wlc、lblc、lblcr、dh、sh、sed、nq。

二、基于主从复制的高可用方案

1、双节点主从 + keepalived/heartbeat

两个节点可以采用简单的一主一从模式,或者双主模式,并且放置于同一个VLAN中,在master节点发生故障后,利用keepalived/heartbeat的高可用机制实现快速切换到slave节点。

注意事项:

  • 采用keepalived作为高可用方案时,两个节点最好都设置成BACKUP模式,避免因为意外情况下(比如脑裂)相互抢占导致往两个节点写入相同数据而引发冲突;
  • 把两个节点的auto_increment_increment(自增起始值)和auto_increment_offset(自增步长)设成不同值。其目的是为了避免master节点意外宕机时,可能会有部分binlog未能及时复制到slave上被应用,从而会导致slave新写入数据的自增值和原先master上冲突了,因此一开始就使其错开;当然了,如果有合适的容错机制能解决主从自增ID冲突的话,也可以不这么做;
  • slave节点服务器配置不要太差,否则更容易导致复制延迟。作为热备节点的slave服务器,硬件配置不能低于master节点;
  • 如果对延迟问题很敏感的话,可考虑使用MariaDB分支版本,或者直接上线MySQL 5.7最新版本,利用多线程复制的方式可以很大程度降低复制延迟;
  • 对复制延迟特别敏感的另一个备选方案,是采用semi sync replication(就是所谓的半同步复制)或者后面会提到的PXC方案,基本上无延迟,不过事务并发性能会有不小程度的损失,需要综合评估再决定;
  • keepalived的检测机制需要适当完善,不能仅仅只是检查mysqld进程是否存活,或者MySQL服务端口是否可通,还应该进一步做数据写入或者运算的探测,判断响应时间,如果超过设定的阈值,就可以启动切换机制;
  • keepalived最终确定进行切换时,还需要判断slave的延迟程度。需要事先定好规则,以便决定在延迟情况下,采取直接切换或等待何种策略。直接切换可能因为复制延迟有些数据无法查询到而重复写入;
  • keepalived或heartbeat自身都无法解决脑裂的问题,因此在进行服务异常判断时,可以调整判断脚本,通过对第三方节点补充检测来决定是否进行切换,可降低脑裂问题产生的风险。

2、多节点主从+MHA/MMM

多节点主从,可以采用一主多从,或者双主多从的模式。这种模式下,可以采用MHA或MMM来管理整个集群,目前MHA应用的最多,优先推荐MHA,最新的MHA也已支持MySQL 5.6的GTID模式了。

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工作原理

MHA的目的在于维持MySQL Replication中Master库的高可用性,其最大特点是可以修复多个Slave之间的差异日志,最终使所有Slave保持数据一致,然后从中选择一个充当新的Master,并将其它Slave指向它。

基本工作流程大致如下:

1) Manager定期监控Master,监控时间间隔由参数ping_interval决定,缺省为3秒钟一次;可利用其自身的监控功能,也可调用第三方软件来监控;MHA自身提供了两种监控方式:SELECT(执行SELECT 1)和CONNECT(创建连接/断开连接),由于参数ping_type决定,缺省为SELECT方式。

2) 当监测到Master故障时,调用SSH脚本对所有Node执行一次检查,包括如下几个方面:

  • MySQL实例是否可以连接;
  • Master服务器是否可以SSH连通;
  • 检查SQL Thread的状态;
  • 检查哪些Server死掉了,哪些Server是活动的,以及活动的Slave实例;
  • 检查Slave实例的配置及复制过滤规则;
  • 最后退出监控脚本并返回代表特殊意义代码。

3) 开始Master故障切换,包括如下几个子阶段:

  • 1: Configuration Check Phase

在这个阶段,若某个Slave实例的SQL Thread停止了,则会自动启动它;并再次确认活动的Servers及Slaves。

  • 2: Dead Master Shutdown Phase

在这个阶段,首先调用master_ip_failover_script,若HA是基于VIP实现的,则关闭VIP,若是基于目录数据库实现的,则修改映射记录。然后调用shutdown_script脚本强制关闭主机,以避免服务重启时,发生脑裂。

  • 3: Master Recovery Phase

又包括如下3个子阶段:

3.1: Getting Latest Slaves Phase

检查各个Slave,获取最近的和最旧的binary log file和position,并检查各个Slave成为Master的优先级,依赖于candidate_master、no_master、[server_xxx]顺序、binary log差异量等因素。

3.2: Saving Dead Master's Binlog Phase

若dead master所在服务器依然可以通过SSH连通,则提取dead master的binary log,提取日志的起点就是上一步获取的最新的binary log file和position,直到最后一条事件日志,并在dead master本地的工作目录(由参数remote_workdir决定)中创建文件保存这些提取到的日志,然后将该文件拷贝到Manager服务器的工作目录下(由参数manager_workdir决定)。当然,若dead master系统就无法连接,也就不存在差异的binary log了。另外,MHA还要对各个Slave节点进行健康检查,主要是SSH连通性。

3.3: Determining New Master Phase

接下来调用apply_diff_relay_logs命令恢复Slave的差异日志,这个差异日志指的是各个Slave之间的relay log。恢复完成后,所有的Slave数据是一致的,此时就可以根据优先级选择New Master了。

3.4: New Master Diff Log Generation Phase

这里是生成dead master和new master之间的差异日志,即将Phase 3.2保存的binary log拷贝到New Master的工作目录中(remote_workdir)。

3.5: Master Log Apply Phase

将上一步拷贝的差异日志恢复到New Master上,若发生错误,也可手动恢复。然后获取New Master的binlog name和position,以便其它Slave从这个新的binlog name和position开始复制。最后会开启New Master的写权限,即将read_only参数设置为0。

  • 4: Slaves Recovery Phase

4.1: Starting Parallel Slave Diff Log Generation Phase

生成Slave与New Slave之间的差异日志,并将该日志拷贝到各Slave的工作目录下,这部分日志dead master和new master之间差异的那部分日志,因为各个Slave在 3.3阶段已经同步了。

4.2: Starting Parallel Slave Log Apply Phase

在各个Slave上应用这部分差异日志,然后通过CHANGE MASTER TO命令将这些Slave指向新的New Master,最后开始复制(start slave)。

  • 5: New master cleanup phase

清理New Master其实就是重置slave info,即取消原来的Slave信息。

至此整个Master故障切换过程完成。

简单的说,工作原理:

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

识别含有最新更新的slave;

应用差异的中继日志(relay log)到其他的slave;

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

提升一个slave为新的master;

使其他的slave连接新的master进行复制;

MHA的优势

1)master自动监控和故障转移
    在当前已存在的主从复制环境中,MHA可以监控master主机故障,并且故障自动转移。即使有一些slave没有接受新的relay log events,MHA也会从最新的slave自动识别差异的relay log events,并apply差异的event到其他slaves。因此所有的slave都是一致的。MHA秒级别故障转移(9-12秒监测到主机故障,任选7秒钟关闭电源主机避免脑裂,接下来apply差异relay logs,
注册到新的master,通常需要时间10-30秒即total downtime)。另外,在配置文件里可以配置一个slave优先成为master。因为MHA修复了slave之间的一致性,dba就不用去处理一致性问题。当迁移新的master之后,并行恢复其他slave。即使有成千上万的slave,也不会影响恢复master时间,slave也很快完成。当其中一个master崩溃,MHA4秒完成故障转移,这是主动/被动集群解决方案无法完成的。
2)互动(手动)master故障转移
    MHA可以用来只做故障转移,而不监测master,MHA只作为故障转移的交互。
3)非交互式故障转移
    非交互式的故障转移也提供(不监控master,自动故障转移)。这个特性很有用,特别是你已经安装了其他软件监控master。比如,用Pacemaker(Heartbeat)监测master故障和vip接管,用
MHA故障转移和slave提升。
4)在线切换master到不同主机
    在很多情况下,有必要将master转移到其他主机上(如替换raid控制器,提升master机器硬件等等)。这并不是master崩溃,但是计划维护必须去做。计划维护导致downtime,必须尽可能快的恢复。快速的master切换和优雅的阻塞写操作是必需的,MHA提供了这种方式。优雅的master切换, 0.5-2秒内阻塞写操作。在很多情况下0.5-2秒的downtime是可以接受的,并且即使不在计划维护窗口。这意味着当需要更换更快机器,升级高版本时,dba可以很容易采取动作。

5)master crash不会导致主从数据不一致性
    当master crash后,MHA自动识别slave间relay logevents的不同,然后应用与不同的slave,最终所有slave都同步。结合通过半同步一起使用,几乎没有任何数据丢失。
6)MHA部署不影响当前环境设置
    MHA最重要的一个设计理念就是尽可能使用简单。使用与5.0+以上主从环境,其他HA方案需要改变mysql部署设置,MHA不会让dba做这些部署配置,同步和半同步环境都可以用。启动/停止/升级/降级/安装/卸载 MHA都不用改变mysql主从(如启动/停止)。
当你需要升级MHA到新版本时,不需要停止mysql,仅仅更新MHA版本,然后重新启动MHAmanger即可。MHA 支持包含5.0/5/1/5.5/5.6。有些HA方案要求特定的mysql版本(如mysqlcluster,mysql withglobal transaction id 等),而且你可能不想仅仅为了MasterHA而迁移应用。
7)不额外增加服务器
    MHA 包含MHA Manager和MHA node。MHA node运行在每台mysql服务器上,Manager可以单独部署一台机器,监控100+以上master,总服务器数量不会有太大增加。需要注意的是Manager也可以运行在slaves中的一台机器上。

8)性能无影响
    当监控master,MHA只是几秒钟(默认3秒)发送ping包,不发送大的查询。主从复制性能不受影响
9)适用任何mysql在主从中适用的存储引擎
    Mysql不仅仅适用于事务安全的innodb引擎,在主从中适用的引擎,MHA都可以适用。即使用遗留环境的mysiam引擎,不进行迁移,也可以用MHA。

MHA的限制

  • 需要在各个节点间打通ssh信任,这对某些公司安全制度来说是个挑战,因为如果某个节点被黑客攻破的话,其他节点也会跟着遭殃;
  • 自带提供的脚本还需要进一步补充完善,当然了,一般的使用还是够用的。

MHA连接切换:

通常有两种解决方案:一是引入VIP,当数据库切换时,VIP随之切换;常用的HA软件中,大多是采用VIP实现的,比如Oracle RAC,SQL Server群集、Heartbeat等。二是采用全局目录数据库,即将应用和数据库之间的连接映射为一个列表,当数据库切换时,更改这个映射列表。MHA并不限制用户使用那种方式,只是通过master_ip_failover_script配置参数提供了一个接口。 若采用VIP的方式来实现,可引入第三方软件,比如Keplived等,也可自行编写一个VIP切换脚本。

3、多节点主从+zookeeper

在大规模节点环境下,采用keepalived或者MHA作为MySQL的高可用管理还是有些复杂或麻烦。首先,这么多节点如果没有采用配置服务来管理,必然杂乱无章,线上切换时很容易误操作。在较大规模环境下,建议采用zookeeper管理集群,可实现快速检测切换,以及便捷的节点管理。

参考

传送门LVS+Keepalived和MHA安装配置:

http://bestvivi.com/2015/09/09/MySQL%E4%B8%BB%E4%B8%BB%E5%A4%8D%E5%88%B6+LVS+Keepalived%E5%AE%9E%E7%8E%B0MySQL%E9%AB%98%E5%8F%AF%E7%94%A8%E6%80%A7/

http://joelhy.github.io/2015/02/06/mysql-mha/