一个系统可能包含很多模块,如数据库、前端、缓存、搜索、消息队列等,每个模块都需要做到高可用,才能保证整个系统的高可用。对于数据库服务而言,高可用的实现可能更加复杂,对用户的服务可用,不仅仅是能访问,还需要有正确性保证,因此讨论数据库的高可用方案时,在容灾之外,还要同时考虑方案中数据一致性问题。
本文将通过介绍一些业界主流的数据库高可用架构、每种方案的特性和优缺点,以及数据库高可用架构的自动化运维实现,讲讲数据库高可用容灾方案设计与实现,希望抛砖引玉,和大家一起讨论。
一、高可用数据库概述
什么是高可用数据库?
高可用数据库是由一系列数据库构成的总体系统,在任何时刻,至少有一个节点可以接受用户的请求并提供数据库服务。大多数数据库架构中,有一个主节点处理主要请求,还有若干备用节点用于容灾切换,当主节点不能提供服务时,备用节点成为主节点继续提供服务,用以保证整个系统的可用和稳定。
高可用数据库有很多优点:
- ***,方便读写分离。数据库请求当中,一般读操作的请求次数远大于写操作,高可用数据库可以通过将写操作放在主数据库节点上进行,将读操作分担到若干从库上,来提升读操作吞吐量,进而提升读写效率;
- 第二,变更不停服。当整个高可用数据库架构或者主节点升级时,可以让高可用数据库先进行主库切换,让备用节点替换原主节点提供数据库服务,当主节点升级完毕后,再将主从库服务切换回来,这样能有效避免系统升级或变更时对用户服务质量产生影响;
- 第三,备份不影响服务性能。高可用数据库架构包含多个从库,在不影响主节点服务性能的情况下,能非常方便地实现数据的容灾备份。
一般,高可用数据库地架构设计时,也需要考虑三个问题:
- ***,如何同步各数据库之间的节点数据?同步需要保证切换后的数据库是***数据,以及在切换过程中数据不会丢失,同时还要考虑同步过程对主库和备库的影响。
- 第二,高可用数据库的容灾切换如何进行?架构不同容灾切换的复杂度也不一样,且切换以后需要保证主、从库数据的一致性,这可能需要开发者在设计之初就尽量优化和简化容灾切换逻辑。
- 第三,如何提高高可用的运维效率?
二、业界典型高可用数据库架构
按照数据同步方式,我们可以将业界主流的高可用架构划分成四种:***种,共享存储方案;第二种,操作系统实时数据块复制;第三种,数据库级别的主从复制;第四种,高可用数据库集群。每一种数据同步方式可以衍生出不同的架构。
方案一:共享存储
共享存储指若干DB服务使用同一份存储,一个为主DB,其他的为备用DB,若主服务崩溃,则系统启动备用DB,成为新的主DB,继续提供服务。一般共享存储采用比较多的是SAN/NAS方案。
这种方案的优点是没有数据同步的问题,但也有一些限制,如对于共享存储的实时性和网络性能有较高要求。因为共享存储一般是通过网络来访问存储当中的数据,在网络性能较差的情况下,数据库的性能也无法达到令人满意的效果。不过,随着硬件性能的不断提升,将计算存储分离、和DB深度结合的共享存储亦是高可用数据库未来发展的趋势之一。
方案二:操作系统实时数据块复制
这个方案的典型场景是DRBD,可以把它理解为远程的RAID1,如下图所示,左侧数据库写入数据以后立即同步到右侧的存储设备当中。如果左边数据库崩溃,系统可以直接激活右边的数据库存储设备,启动新的数据库服务,实现容灾切换。
这个方案同样有一些问题,如系统只能有一个数据副本提供服务,无法实现读写分离;另外,如果系统崩溃,主库进程中断,容灾切换后需要在挂掉的数据库上做数据库崩溃恢复,系统需要的容灾恢复时间较长。
方案三:数据库主从复制
这种方案我认为是最经典的数据同步模式,系统采用一个主库和多个从库方式,其实现原理主要是基于日志的主从复制,主库操作以日志的形式发送给各个从库,从库接收到日志后进行数据备份。这种方式的好处是一个主库可以连接多个从库,能很方便地实现读写分离,同时,因为每个备库都在运行中,所以备库里面的数据基本上都是热数据,容灾切换也非常快。
不过,这个方案也并非***无缺,如容灾切换时,从库一定要同步完***数据以后才能升级为主库,否则极有可能发生数据丢失的情况。针对传统主从架构的一些问题,业界也逐渐研发出对应的改进技术。
改进技术一:双主架构
问题:经典主从架构里面,原主库崩溃恢复的过程中,新的数据无法及时同步到该数据库当中,原主库恢复后,需要重新设置为从库,并将容灾过程中的数据重新同步进行。
改进措施:为了保证容灾后的数据一致性,业界对这种架构做了一些改进,其中一种改进措施就叫双主架构,如下图所示,双主架构一般会选择两个DB做一对主库,这两个DB之间互相为对方的从库,无论往哪个DB写入数据,另一个都会自动同步。容灾时系统只需要把流量从左边切换到右边,容灾后数据同步依旧自动进行,这样,就保证了容灾后原主库的数据一致性。
改进技术二:日志自动寻址
问题:容灾备份时,当某一从库提升为主库后,其他备库需要自动定位新主库的日志同步点,同步新主库的日志。早期数据库日志中,MySQL是通过文件名加上文件的偏移量进行寻址,因此,主库的自动定位并不好实现。
改进措施:为了解决此问题,MySQL提供了一种叫做GTID的全局事务标志技术,一个事务对应一个ID,所有的日志都带有唯一的标识符,主从库切换后,其余从库只要根据新主库的日志ID,就可以辨别新的日志同步点,然后根据这个日志同步数据,这对于搭建一主库多从库的架构来说寻址非常便捷。
改进技术三:异步复制改进
问题:默认情况下,MySQL的复制是异步的,主库将新生成的日志发送给各从库后,无需等待从库的ack回复(从库将接收到的日志写进relay log后,才会回复ack),直接就认为这次DDL/DML成功了。但在极端情况下,如主库刚提交日志,其他从库还没有接收到相关日志时,数据库发生故障,此时,该日志的内容就会全部丢失。
改进措施:半同步复制机制。半同步复制是指主库在将新生成的日志发送给各从库前,需发送日志到一个(默认)从库,等待从库返回ack信息后,主库再提交日志发送给各从库,这就防止了上述情况下的数据丢失。半同步复制是一种提升数据一致性的有效方式,也是比较关键的技术。
方案四:数据库高可用集群
前面三种方案主要是通过日志的复制模式实现高可用,第四种方案则是基于一致性算法来做数据的同步,数据库提供多节点一致性同步机制,利用该机制构建多节点同步集群。这种方式比较经典的案例包括MGR(MySQL Group Replication)和Galera等,最近业内也有一些类似的尝试,如使用一致性协议算法,自研高可用数据库的架构等。
以上示意图有五个节点,他们之间是构建成了一个一致性的同步集群,客户端可以读写其中的任何一个节点,任意一节点写入,其他节点都能够将数据进行同步,因此,理论上每个节点都可以进行读写操作。这种方式的容灾实现也比较简单,假设第二个节点出现故障,系统只需要断开客户端对第二个节点的访问路径,其他节点照常访问就可以了,这也是业界近年来比较流行的高可用集群方案。
UCloud高可用数据库解决方案UDB
UCloud对比了业内的各解决方案的优劣点,综合了原生MySQL兼容,不同版本、不同应用场景的覆盖等多种因素,最终选择采用基于数据库主从复制的方式实现高可用架构,并在原架构基础上,使用双主架构、半同步复制、采用GTID等措施进行了系列优化,保证数据一致性的同时,实现日志的自动寻址。
如上图所示,***层为数据层,使用了双主架构,主库与备主库之间通过半同步的方式实现数据同步,整个数据层是双主架构+半同步架构的模式。中间层有一个代理服务器Proxy,Proxy将流量导入到双主数据库的主节点,架构使用了GTID的模式,方便从库自动寻址。
系统的容灾切换也非常简单,数据库崩溃前,Proxy将流量导到主DB上,发生容灾以后,只需要把Proxy从左边Master导到右边的Slave,即可快速完成切换。
三、高可用数据库的自动化运维
自动化运维的重点方向
自动化运维是高可用数据库中的难点,因为企业业务不一定只有一个数据库,可能需要同时管理十几个甚至上百个数据库,如果每一个数据库都配置一个高可用数据库架构,系统则需要保证其中任何一个发生问题以后都可以进行容灾,这无疑给运维带来了极大挑战。
那么,如何同时管理大量高可用数据库,让他们都可以进行容灾呢?这里有一些自动化运维方向的思路:1、容灾切换自动化;2、高可用数据库运行状况监控;3、健康状况自动检查和问题修复。
1、容灾切换自动化。要实现容灾切换的自动化,首先需要考虑两个问题:
***,怎样准确判断需要容灾。这是实现自动容灾的基础和前提,它需要结合实际情况讨论和判断。如发生网络波动时,可能有一段时间发现无法连上主库,实际上几秒钟以后整个业务系统又恢复了,如果这时候数据库做容灾的话代价比较大,且容灾后还可能会有额外的风险。所以需要在前期准确判断是否需要容灾,并保证在最需要容灾的时候及时容灾;
第二,容灾切换时,备库数据尽量和主库数据保持一致,否则,就会带来数据丢失的问题。
针对上述问题,MySQL已经有比较常用方案供参考,老牌的如MHA,还有一种比较新的方案叫Orchestrator,如果大家自己搭建数据库,可以考虑采用这两种方案。
2、健康状况自动检查。健康状况检查需要通过自动监控搭配告警来做,高可用容灾中,最关心的还是高可用数据库的主库和备库数据是否一致,一般情况,导致主从库数据不一致的主要是两点:
***,复制有没有正常进行,如发送日志时主库与备库之间的连接突然断掉,这时候需要系统时常扫描主备库是否异常;
第二,主从延时,如果主从之间的数据延迟较大,那么切换数据库时也会比较麻烦,这方面也可以考虑使用业内比较常用的监控模块如Prometheus等工具定期采集,发现异常状况后及时调整。
第三,异常情况自适应调整。以主从延迟为例,一般来说可能是CPU的问题或者IO的问题等,如果是IO的问题,一种办法是将IO调高,这是一种比较好的解决方案,如果IO调高以后发现还是无法降低延时,可以在从库把日志的持久化等级暂时性调低。当然,如果主从之间延迟过大,完全无法调整为正常水平,这时候就要考虑通过一些手段重做从库。
UDB:海量高可用数据库自动化运维
UDB拥有海量的高可用数据库,在自动化运维和管理方面,UDB采用的是高可用容灾集中式自动化管理的方式,通过自研的自动容灾逻辑,进行大规模、高并发的DB自动化容灾。同时,UDB的运维体系还可以做到自动化的问题探测以及问题修复,如自动拉起DB、恢复服务,自动恢复数据同步,自适应流量控制等。此外,UDB还会配合一些高效运维工具和巡检工具做更深层次的问题的发现和解决。
在UDB高可用运维当中,有几点经验可以跟大家分享:
- ***,日常需要做例行巡检,保证高可用数据库的健康。主从延时是导致高可用数据库无法容灾的关键原因之一,这一点一定要在日常运维工作中重视起来;
- 第二,定期容灾演练很有必要。容灾演练就是在平台上跑自己的容灾逻辑,我们需要在不同场景下做切换,看数据有没有丢失、是否保持了数据的一致性等等,因为线上环境非常复杂,可能会有各种莫名其妙的问题导致切换逻辑在发生切换以后结果不一致,所以要通过定期演练把各种可能性降到***;
- 第三,高可用切换需要记录日志,并且在切换失败的时候马上告警。切换日志可以做事后复盘分析,看这个DB是什么时候崩溃做的容灾。进入告警后可以保证***时间介入并解决,缩短整个DB崩溃对用户的影响时间。
四、总结
高可用架构是数据库运行稳定必不可少的一部分,设计架构时要考虑诸多问题,如数据是否同步、高可用自动切换、自动化运维等等。前面讲解了四种基于数据库同步的数据库高可用架构,如果是在云环境下,推荐使用UDB云数据库这样的产品一键完成上述配置,帮助减轻业务的运维压力。
作者介绍
丁顺,UCloud资深存储研发工程师,在云产品、大规模海量存储方面具有丰富的经验,擅长于分布式系统、面向服务、容器化、高可用等方面的架构和软件设计。