本文分享自华为云社区《DTCC 2023专家解读丨GaussDB技术解读系列之应用无损透明(ALT)》,作者:GaussDB数据库。
近日,在第14届中国数据库技术大会(DTCC 2023)的GaussDB“五高两易”核心技术,给世界一个更优选择专场,华为云数据库技术专家徐宜良分享了《GaussDB高可用之应用无损透明》主题演讲,介绍了华为云GaussDB高可用方面的最新成果。
以下为演讲实录:
大家下午好!下面由我来为大家介绍GaussDB高可用之应用无损透明特性。
一、GaussDB应用无损透明特性简介
我们知道用户在使用数据库在线业务系统时,如果数据库服务端发生了维护操作,比如说重启或者主备切换,或者发生故障时,应用程序会感应到数据库之间的连接发生中断,一些执行的事务会被自动回滚掉。当数据服务恢复之后,应用程序需要重建连接,,这样对业务来说不仅增加了业务系统的开发复杂性,也增加业务运行风险。
我们知道数据库发生异常时,我们无法判断正在执行的事务是否提交完成。为了解决连接中断和事务自动回滚的问题,华为云GaussDB数据库提供了应用无损透明的高可用能力,通过这个能力我们实现了连接保持和事务断点继续(从事务中断的地方继续执行)的功能。
GaussDB应用无损透明支持在数据库内部自动判断事务边界,缓存当前事务执行的会话信息和数据信息,这些信息包括会话锁、用户变量等内容。在数据库恢复时,可以根据这些缓存的会话信息和事务信息,以及服务端的日志一起自动构建恢复出一个一致性的快照点,我们可以通过这个一致性快照点恢复出数据库发生主备切换那一刻所有的应用会话,恢复主备切换那一刻未提交的事务状态,当会话和事务状态都被恢复之后,我们可以从事务的一致性点上继续往下执行事务。
从业务视角来看,如果使用应用无损透明功能,整个数据库在发生主备切换期间,应用程序只是感知到事务执行稍微变慢了,不会感知到事务执行中断,也不需要进行重建连接,更不需要进行事务的重试,简化了业务程序的开发复杂性,降低了风险。
二、GaussDB应用无损透明的架构
我们看一下GaussDB数据库的应用无损透明架构。刚才提到两个特性,一个是连接保持,一个是事务的断点继续,针对连接保持,业界常用的解决方案是,在应用程序和数据库之间部署一个中间件,中间件对数据库和应用程序的连接起到转发作用,当数据库服务端发生主备切换,断开了数据库和中间件之间的连接,应用程序和中间件之间的连接没有断,从表现上看好像解决了连接保持的功能,但我们知道中间件和数据库之间的连接还是发生了中断,连接断了之后会话级参数就丢失了。数据库进行主备切换,在备库升级为主库的时候,所有未提交的事务自动回滚掉了。中间件是独立的,它跟数据库没有任何关系,解决不了事务断点继续的问题,而且中间件不仅在调用链上多了一环,增加了高可用的复杂性和风险,还需要额外的部署、增加了资源消耗。
GaussDB数据库没有使用中间件方式,而是直接把能力构建在驱动层。当数据库服务端主备切换或者发生故障时,驱动层不会把中断信息上报到应用程序,而是在自己内部进行连接保持,保持的时候缓存了一些会话数据和事务数据。当数据库服务端恢复之后,驱动会自动建立一个新的会话连接,利用缓存的会话数据,恢复原来连接上会话级的参数。会话级参数恢复之后,根据缓存的事务信息继续恢复原来未提交的事务状态,这样会话和事务状态都恢复之后,事务可以从它主备切换时的一致性快照点继续执行。
刚才提到主库宕机备库升主之后,一般数据库会把未提交的事务回滚掉,针对这种未提交事务的回滚问题,GaussDB在启动应用无损透明功能之后,未提交的事务不能自动回滚,需要保持未提交事务的状态,等待新建的连接过来之后进行事务的恢复和桥接事务。这个地方我们引用了逻辑事务ID的功能,通过逻辑事务ID和真实的事务ID匹配,去判断事务的状态有效性。如果事务状态是有效的,就会把事务信息绑定到连接上,实现了数据库备库升主库之后未提交事务状态的恢复。
当数据库发生主备切换的时候,连接发生中断,应用程序也不知道数据库发生了什么,也不知道数据库什么时候恢复,一般的策略会采用定时的重试,不停地去连接,查看数据库是否正常
这种定时尝试机制存在两个问题:一个是,数据库服务正在恢复期间,不停的尝试会不断的报错,无效且多余的操作;二是,定时检测机制存在延时问题,当数据库服务恢复后,应用无法实时的感知服务恢复了。GaussDB 提供了一种实时消息通知服务(简称GNS),当数据库服务端状态发生任何变化的时候,可以及时的发送消息事件通知给应用程序,应用程序收到之后可以进行相应的动作。GaussDB消息通知服务是一种实时的主动推送的方式,时延更低,消耗资源更少。
三、GaussDB应用无损透明的使用方式
说到应用无损透明,其使用方式非常简单,只需要在应用程序向数据库建立连接时打开功能开关即可。例如以JDBC驱动为例,当应用程序想使用应用无损透明功能时,只需要在JDBC的URL中配置GaussDB消息通知服务(简称GNS)的IP地址和端口即可。这时会有一个情况,一个数据库集群有很多应用程序客户端,有的应用客户端想用应用无损透明功能,有的应用程序不用,打开或关闭应用无损透明功能这两种情况同时存在,那么当数据库发生主备切换时,使用应用无损透明功能的应用程序客户端,就会具备连接保持和事务断点继续的能力,这个时候的数据库主备切换操作对业务来说是无感知的。没有配置使用应用无损透明功能的应用程序客户端,当数据库发生主备切换或者异常时,可以立即感知到连接中断,数据库正在执行的事务会立即回滚掉。
我们看到GNS是对等多活的,当客户端很多时,可以连接到不同的GNS,相当于负载均衡的功能,而不是像主备方式那样,把所有的资源压在一台物理机上。
四、GaussDB应用无损透明的使用场景
刚才介绍了一下架构原理和使用方法,下面介绍GaussDB数据库的应用无损透明使用场景,主要包括计划内主备切换、计划外主备切换、容灾切换等三个方面。
计划内主备切换
计划内主备切换一般都是数据库在进行例行的维护和升级中用到的,由运维管理员主动发起。在做计划内主备切换时,GaussDB会自动判断和等待达到一个安全的事务边界后,在驱动层缓存刚才说的会话数据和事务数据,把数据缓存完之后数据库再进行主备切换。
安全的事务边界是指当前会话上的事务执行到某一个一致性点,可以分为两种情况,一是执行完事务后进行主备切换,即事务级排空,二是执行完一个SQL语句即可进行主备切换,即语句级排空,这个时候事务属于未提交状态,可以说语句级排空对业务影响更小一点。
在整个数据库主备切换期间,GaussDB驱动进行连接保持,当数据库服务恢复了之后,先重建连接,再去恢复事务,事务恢复之后从事务一致性点继续执行。我们可以看到在正常的计划内主备切换的场景下,使用应用无损透明特性,对数据库来说是无感知的,而且这种主备切换会使用语句级排空。OLTP场景下,SQL语句执行时长都是毫秒级的,使用应用无损透明功能下的主备切换只是多增加了一个SQL语句执行时间的等待,也就是多等待一个毫秒级的时间,相对于原来几秒甚至几十秒的主备切换时间来说,多增加出来的毫秒级等待时间几乎是可以忽略不计的。
计划外主备切换
下面我们看一下计划外的场景。计划外可以说是灾难性的,突发的,它和计划内的主备切换场景的部分处理机制是有所不同的。针对计划外的主备切换,GaussDB数据库通过基于事务粒度来缓存整个事务里的语句和重放整个事务来实现。GaussDB自动以事务作为一致性边界,在事务执行过程中,驱动自动缓存执行过的事务SQL语句。数据库服务恢复后,GaussDB重新执行缓存的事务SQL语句,为了避免重复执行和提交事务,驱动重放时会首先根据逻辑事务ID来查询事务执行状态,如果事务已经提交了就不需要再执行。
之所以采用事务粒度重放,而不是以语句粒度重放,是因为数据库的主库和备库之间的数据同步,是以事务为单位的,当事务在主库上被提交了,为了保证数据不丢失一定会把事务的wal日志实时同步到备库上,这是数据库的主备数据复制的一个通用基本的机制,已经完全能满足事务粒度重放的要求,而如果要使用语句粒度的重放,必然需要采用一些其他额外的手段措施,例如使用savepoint作为主备实时同步边界,用来阶段性保存进度等,和事务粒度重放相比,语句粒度重放使得方案更复杂,覆盖的场景更少,性能更差。
容灾切换
我们看一下容灾场景。异地容灾是两个城市相距几千公里,时延在几十毫秒,这么大的时延很难要求跨地区访问数据库,所以异地场景的容灾切换是数据库的容灾和业务程序容灾相互配合,同时切换的过程。目前容灾切换面临一个困境,因为这两个切换是互相独立的,数据库集群切换完了,而应用程序却没有切换完,端到端看数据库恢复了,但是业务没有恢复。
为了解决端到端的问题,GaussDB提供了一个消息通知服务功能,即GNS。当数据库发生容灾切换时,比如说生产集群降为灾备集群时,会立即把消息发到应用,应用程序收到数据库集群降备的事件通知后,就可以立即进行主备切换;当数据库容灾集群升为主集群时,GNS会及时通知到应用程序,应用程序收到消息之后,就可以立即切流以恢复业务。这样一个相互配合的机制,可以解决端到端的RTO时长问题,不需要多余的等待,也不需要人为判断。
除了异地容灾外,还有一种同城容灾部署场景,因为是同城,所以时延比较低,网络环境比较好,同城容灾这种场景下,可能只是数据库集群发生切换,而应用程序保持不变。这种场景如果我们使用GaussDB提供的应用无损透明机制,也就是通过连接保持和事务断点继续技术,在同城容灾切换时,在确保RPO=0不丢数据的情况下,还能保证数据库的容灾切换对应用程序也是透明的。