MySQL是数据库领域当之无愧的霸主之一,其在各行各业被广泛应用,随着广泛使用,对于MySQL本身的高可用性的要求就是不可避免的话题,而MySQL的高可用方案也随着MySQL功能的完善经历了多次升级,本文将对MySQL的各种高可用架构进行分析,以此来了解架构的演进。
冗余是高可用设计的核心
高可用的核心是避免单点故障(SPOF),而避免单点故障的最经典的解决方案是增加冗余。
不同的高可用方案在冗余方式和冗余的程度上有所差别。
冗余方式上面,有些是在底层存储上进行冗余,有些是对整个主机进行冗余,有些是跨IDC的冗余。
冗余程度上面,有些是灾备级别允许一定程度的数据丢失,有些也是要求数据的强一致性。
MySQL的各种高可用方案的核心就是围绕着冗余的设计展开。
MySQL复制技术发展史
MySQL的高可用方案基于MySQL的复制技术,复制技术的核心就是增加一个MySQL节点的冗余。
1. MySQL Replication引入
2000年,MySQL 3.23.15版本引入了MySQL Replication技术,一经推出就得到了较为广泛的使用。Replication是一种异步的数据复制机制,实现的是近实时的数据同步效果。此时的Replicaton主要通过两个线程实现,一个在Master节点,一个在Slave节点。Slave首先通过Master获取到数据变动的event,然后将这个event在Slave节点进行replay重放。
这种方式存在一个比较明显的缺点,那就是replay会涉及到数据的写入,属于IO操作,速度比较慢,因为读取event和replay是在同个流程中,replay速度慢会导致读取event的缺速度也比较慢,当主节点写入的速度较快的时候,就会导致大量主备延迟,binary log会积压大量没有备份到Slave的情况,一旦Master节点出问题,Slave节点启用的话会出现大量数据落后的不一致情况,且Slave节点也无法作为读节点对外提供服务。
2. Relay Log引入
2002年,MySQL4.0.2引入了relay log,将Slave端读取event和数据replay分开成了两个流程,分别由IO线程和SQL线程两个线程负责。其中,IO线程负责从Master节点读取event,然后写入本地的relay log,SQL线程从relay log中读取event然后执行,将数据写入本地库。这样子一来,即使SQL线程执行缓慢,也只是relay log挤压,Master的binary log会通过IO线程尽可能快地同步到Slave节点,一旦Master出问题,切换到Slave,不会出现大量数据丢失不一致的情况,虽然还是有可能部分数据未及时通过IO线程写入relay log,但是程度大大地减轻了。
3.半同步复制引入
2010年,为解决异步复制Slave节点可能在Master宕机的情况下丢失binary log的问题,引入了半同步复制。在半同步复制的机制下,Master节点在应答客户端提交的事务之前需要保证至少一个Slave接收到Master的event并写realy log成功。
当然半同步还是存在一些问题:
1、解决了Master宕机情况下relay log丢失的问题,但是仍然非强一致性,relay log可能还未被SQL线程写入本地库,此时的查询仍然会有数据落后的可能。
2、主节点宕机,binary log还未传给半同步节点,但是已经写入本地binary log,此时切换到半同步节点运行,等待原主节点恢复以后,已经写入的binary log会被继续传给半同步节点,可能造成主键冲突。
3、无法很好的支持故障自动切换的场景。
4.组复制的引入
2016年,MySQL5.7.17版本引入了Group Replication技术,这是一个“逻辑上”的同步的机制,在第一个节点收到一个事务时,会将事务广播到集群中的其他节点,等收到过半数节点同意以后,事务会在各个节点上独立提交,也就是说各个节点只是在决定事务是否冲突、能否提交的阶段是同步的,而事务的提交是异步的。Group Replication技术是一项支持高可用、强数据一致性的方案,并且最重要的是将不再仅仅只是着眼于提供一个冗余备份,而是从一个集群的角度上来保障高可用和数据一致性,支持流控、故障自动切换等特性,运维比较简单,在高可用和性能上实现了较好的平衡,整体优缺点总结如下:
优点:
1、强一致性:基于分布式paxos变种协议实现组复制,保证数据强一致性;
2、高容错性:自动故障和节点异常检测机制,集群过半数节点正常运行就可以保证集群的可用性。
3、跨机房部署:过半数的节点的机制,适合跨机房的集群容错部署,同个机房内的节点网络间通讯的延迟较小。
4、高扩展性:节点的增加与移除会自动更新组成员信息,新节点加入后,自动从其他节点同步增量数据,直到与其他节点数据一致,过程简单,无需过多的人工干预。
5、多种模式:支持单主与多主模式
缺点:
1、集群要求比较稳定的网络环境,不适用于WAN场景。
2、多主情况下容易有冲突发生,造成业务交易成功率低。
3、资源消耗较多
其他的高可用方案
- 基于异步复制的主从方案
最常见的高可用方案之一是采用异步复制的方式,增加一个或者多个从节点,以实现主节点异常时可以快速切换,这种情况下经常会有binary log落后的情况,一般情况下也无法很好的实现自动切换,所以很多时候作为灾备使用,并且业务上能够接受一些数据丢失的情况。 - 使用SAN共享存储
传统的数据库产品会使用SAN共享存储在存储数据,多个数据库实例并发访问共享存储存取数据,应用通过虚拟IP访问数据库,当某个数据库挂掉以后会由其他正常的实例接管虚拟IP继续对外提供服务。这种方案有明显的问题,一在于共享存储的成本高,二在于共享存储本身又称为了单点。 - 使用DRBD网络RAID方案
DRBD是一个用软件实现的、无共享的、服务器之间镜像块设备内容的存储复制解决方案,实际使用并不多,主要原因在于DRBD本身速度会成为瓶颈,并且通过基于块的存储复制,只能作为灾备,无法同时对外提供服务,存在比较大的资源浪费。 - 使用NFS等网络文件系统
这种方案类似使用SAN共享存储,但是性能会更差,网络文件系统难以实现高吞吐,瓶颈非常明显。 - 使用分布式文件系统
使用分布式文件系统存放数据是另外一种考虑的方向,不同的数据库实例可以使用分布式文件系统的数据,一致性和高可用交由底层分布式文件系统处理,但是这种模式下也很难实现故障的切换,并且引入分布式文件系统更加复杂。 - 使用主主架构
主主架构其实本质上也是异步复制,相对于主从,主主架构的好处在于当其中一个节点故障时可以直接切换,免去了从节点切换为主节点的流程。但是,一般建议不要使用,因为可能存在主键冲突、从节点上误操作同步到了主节点等情况,使用主从架构更加稳健。这种架构适用于对数据没有强一致性要求,允许丢失少量数据的情况,当做灾备或者提供更大的读能力的场景。 - MariaDB Galera Cluster
MariaDB是Mysql的一个分支,在业内也是被广泛使用的,Galera Cluster是MariaDB提供的高可用的集群方案,其在MySQL InnoDB存储引擎基础上打了wrep(虚拟全同步复制)patch,提供了强一致性、高可用的能力,Percona/MariaDB各自的发行版都支持了这个功能,目前支持XtraDB/InnoDB存储引擎。Galera Cluster有以下优缺点:优点:
1、同步复制(注意,这里的同步仍然是指事务发送到各个节点的过程,事务在各个节点的应用的过程仍然是异步的,各个节点独立的)2、真正的 multi-master,所有节点可以同时读写数据库3、自动的节点成员控制,失效节点自动被清除4、新节点加入数据自动复制、支持并行复制5、事务不丢失,不存在主从不一致的情况下缺点:
1、一般只支持三个节点,网络越慢,主节点越多,则越容易有性能的瓶颈,集群扩展性受限。2、事务的提交需要等待集群所有节点的确认回复,无法支持跨机房部署的场景,因为跨机房的网络抖动延迟较大。3、多主情况下容易有冲突发生,造成业务交易成功率低。4、非MySQL官方,虽然社区也很优秀,但对于一些企业来说,会要求官方版本。
- MySQL NDB Cluster
MySQL NDB Cluster是MySQL官方提供的集群同步方案,是一个真正全同步的方案,整体架构如下:
集群分为三种角色:
Management Node
实现对集群其他节点的管理,维护元数据信息,例如数据节点内存大小、数据节点数据存放位置,SQL节点位置信息等。
SQL Node
数据节点不直接提供应用程序访问,SQL节点对接应用程序,转发请求到数据节点,Cluster中可以有多个SQL节点,每个SQL节点查询到的数据都是一致的,一般来说,SQL节点越多,分配到每个SQL节点的负载就越小,系统的整体性能就越好。
Data Node
存取数据,提供真正的数据查询操作。
依赖集群自身提供的同步机制,每个数据节点中的数据都是强一致的,事务的执行是同步的。
NDB Cluster的优缺点都比较明显:
优点:
1、数据能够实现自动分片,具备较强的写入扩展能力。
2、分布式、无共享架构,强一致性,具备较强的故障恢复能力。
3、基于内存,实时性较高,性能较好。
缺点:
1、数据存放在内存,扩展能力受到内存大小的限制。
2、随着节点数量的增加,网络通讯的代价会越来越高,性能会容易产生瓶颈。
3、引入了Management Node和SQL Node,集群管理成本显著增加。
故障切换的方式
随着不同的高可用架构的出现,伴随而来的是多种不同的故障切换的方式,不同的高可用架构需要配套合适的切换方式才能真正发挥故障容灾的作用。
1、应用修改配置切换
当某个数据库节点出现故障以后,手工修改配置指向备库节点,需要重启服务,人工介入,效果极差。
2、DNS动态解析
使用域名访问数据库,采用DNS解析的方式将具体连接的IP信息返回给应用程序,编写特定的检查脚本检测主节点的可用性,当出现故障时动态修改DNS解析到备节点。这种方式的困难点在于DNS会有有效期内的缓存,虽然可以调整缓存时间,但操作起来还是不够方便。
3、MMM
MMM(Master-Master replication manager for MySQL),是一套支持双主故障切换和双主日常管理的脚本程序,其原理是通过漂移虚拟IP的方式来处理单点故障,主要应用于MySQL双主模式,注意,双主只是意味着两个节点都可以当作主节点使用,但是同一时刻只能有一个主节点对外提供服务。
其架构图如下所示,每个节点上都安装了mmm_agent,用于与mmm monitor通讯。
mmm_monitor:监控进程,负责所有的监控工作,决定和处理所有节点角色活动。
mmm_agent:运行在每个mysql服务器上的代理进程,完成监控的探针工作和执行简单的远端服务设置命令。
mmm_monitor端会决定哪些VIP应该挂载哪个mysql节点上,当某一个节点出现异常,其能够将VIP切到其他的节点。
值得注意的是,MMM模式使用起来并不方便,生产应用证明也不是很可靠,故应用不广泛,项目已经很久没有更新了。
4、MHA
MHA(Master High Availability)是目前相对成熟的一套方案,用于进行故障切换和主从提升,能够在0~30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性。
MHA支持修改全局配置以及漂移虚拟IP,能够实现故障切换对应用无感知,应用比较广泛,被普遍生产应用证明了可靠性。
MHA架构引入了MHA Manage,可以独立部署在一台服务器上MHA Manager会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master,然后将所有其他的slave重新指向新的master。整个故障转移过程对应用程序完全透明,MHA模式适用于一主多从的场景。
5、自定义Proxy
采用Haproxy等负载均衡设备,在Haproxy上配置虚拟IP,应用程序访问虚拟IP,haproxy负责进行连接管理和请求的转发,另外可以编写故障检查脚本,当发现故障节点,haproxy自动将相关请求转发到其他节点,实现自动恢复,这是一种比较灵活的方案。
总结一下,本文从复制技术开始,逐一分析了Mysql从最基本的异步复制到组复制,业内常用的多种高可用方案和故障切换方式,也对相关方案的优缺点进行了讨论。实际应用中,需要根据具体业务场景进行方案的选择,综合对于数据一致性的要求、运维复杂程度、跨机房的要求等方面的考虑,选择合适的方案。