【华为云MySQL技术专栏】TaurusDB 全局一致性,保障客户数据强一致

举报
GaussDB 数据库 发表于 2025/03/20 18:11:50 2025/03/20
【摘要】 1. 背景介绍随着信息技术的飞速发展,企业业务场景变得日益复杂多样,数据量呈爆炸式增长。传统单一节点数据库,已难以满足大规模数据处理、高并发读写以及高可用性方面的需求,多节点、多副本数据库应运而生,其中数据一致性问题成为关键难点。在无法保证最终一致性的情况下,主备复制延迟会导致从不同节点查询到的结果不同。对于金融、游戏等对数据延迟敏感的行业而言,只读节点的数据延迟可能导致交易数据错误、业务逻...

1. 背景介绍

随着信息技术的飞速发展,企业业务场景变得日益复杂多样,数据量呈爆炸式增长。传统单一节点数据库,已难以满足大规模数据处理、高并发读写以及高可用性方面的需求,多节点、多副本数据库应运而生,其中数据一致性问题成为关键难点。

在无法保证最终一致性的情况下,主备复制延迟会导致从不同节点查询到的结果不同。对于金融、游戏等对数据延迟敏感的行业而言,只读节点的数据延迟可能导致交易数据错误、业务逻辑混乱等严重后果,直接影响企业运营的准确性与稳定性。

TaurusDB是一款基于存算分离架构的云原生数据库,同样面临着数据一致性的挑战。为解决这一问题,TaurusDB通过在代理层和数据库内核之间构建一套高效的一致性协议,实现了对全局一致性的支持,为用户提供可靠、高效的数据管理解决方案。

本文将从全局一致性的使用方法、原理介绍以及性能分析等方面,对TaurusDB的这一特性进行详细介绍。

2. 使用方法

全局一致性,是指在多节点、多副本的数据库环境中,保证发往集群任意节点的读请求,都可以获得强一致性的结果。

也就是说,无论事务在哪个节点执行,所有客户端都能看到最新的数据,就像系统只有一个单一的数据库副本一样。所有客户端无论访问哪个节点,都能立即看到最新写入的数据,从而确保了数据在整个系统范围内的准确性、完整性和连贯性,避免了数据读取不一致的问题。

TaurusDB的全局一致性功能需要用户创建数据库代理[i] ,并通过数据库代理访问数据库实例,如图1所示。其中,数据库代理是TaurusDB和应用服务之间的网络代理服务,负责代理应用服务访问TaurusDB的所有请求。后文中,proxy均指数据库代理。

截图1.PNG

图1 代理访问路由到主/只读节点[ii]

TaurusDB支持在创建数据库代理时设置一致性级别,也支持在数据库代理创建成功后修改一致性级别。

1. 当用户通过管控界面,修改代理的一致性级别,选择使用全局一致性,并设置超时时间、配置分发策略后,proxy节点会识别到此功能已开启。此后,每当代理节点向 TaurusDB 内核新建一个会话连接时,就会在会话连接上打开开关和设置超时时间。2. 由于代理的实例往往是采用多proxy架构,即不同proxy负责代理不同的业务,每个代理上各自配置各自的一致性级别。这样好处是可以按照不同业务灵活使用全局一致性。

截图22.PNG

图2 全局一致性开关选择 

对于全局一致性,还需要在TaurusDB实例的“参数修改”页面,将参数‘innodb_rds_trx_use_commit_lsn’设置为`ON`。该参数为TaurusDB内核层全局一致性的功能开关,默认为`OFF`,只有将其设置为 `ON`,全局一致性功能才能完整生效。

在代理的“参数修改”页面中,提供了两个与全局一致性相关的参数,具体如下所示。

截图2.PNG

表1 数据库代理参数说明

3. 原理介绍

前置技术背景

TaurusDB只读节点和主节点共享底层的存储数据,但为了保证只读节点内存中缓存数据的一致性,主节点与只读节点通信后,只读节点仍需要从Log Store中读取主节点生成的Redo log(Redo 日志),来更新内存中的缓存数据。这是导致只读复制延迟的由来,也是主节点和只读节点读取数据存在延迟的关键因素。

只读延迟指标:指在主节点更新数据后,多少时间后,只读节点才能得到这个最新数据。 

只读节点通过读取Redo日志来进行缓存数据更新,已更新的Redo日志的LSN(日志序列号),称为visible lsn,表示只读节点能读取数据页的最大LSN

对于主节点来说,所有数据修改产生的Redo日志,经过刷盘后的LSN,称为flushed to disk lsn(刷盘LSN),表示主节点能访问的数据页的最大LSN。只读节点只能读取已刷盘的Redo日志,同时也是只读节点能读取的最大LSN

只读延迟的计算:

只读延迟,其实就是只读节点visible lsn相对于主节点flushed to disk lsn的延迟。比如,在t1时刻:主节点flushed to disk lsn=100, 只读节点visible lsn=80, 经过一段时间,只读节点回放Redo日志后,在t2时刻:主节点 flushed to disk lsn=130,只读节点visible lsn=100。

此时,我们可以计算出只读延迟为:t2-t1,因为经过t2-t1的时间后,只读节点才能读取主节点t1时刻之前提交的数据。

实现原理

参考图1,在全局一致性功能开启之后,当某一个会话数据更新操作执行完成后,主节点的flushed to disk lsn会被更新为最新的LSN,后续读请求进来时,数据库代理会按照代理的路由模式直接路由到预期的节点上。由于存在只读延迟间隙,只读节点上当前visible lsn可能仍滞后于主节点的flushed to disk lsn

内核层面此时会立即加快只读节点的LSN推进,在毫秒级内完成只读节点和主节点的LSN同步。同步完成后,再对该读请求进行响应,保证只读节点能读到,查询请求下发之前所有在主节点上已经提交的更新。

整体流程

图3展示了全局一致性整体工作流程。图中将整体框架划分为三个层面,分别为用户面、proxy层面以及TaurusDB内核层面,并且详细描述了从全局一致性功能的开启到生效,再到内核层控制只读节点全局一致性的细节。

截图3.PNG

全局一致性整体流程示意

下面将从不同层面按照时间流向,对全局一致性功能的整体流程进行说明:

(1)用户面向代理层发送业务SQL请求。

(2)代理层将更新业务SQL请求路由到读写节点node0,主机刷完Redo日志后,将LSN推进到70。

(3)代理层将此时的查询业务SQL请求路由到只读节点node1,并在当前连接中附上全局一致性开关和超时时间标识。

4node1收到SQL请求后,等待自身LSN从60推进到70后,返回查询结果。断开连接后,全局一致性开关参数失效。

(5)代理层将查询业务SQL请求路由到只读节点node2,并在当前连接中附上全局一致性和超时时间标识。

6node2收到SQL请求后,等待此时自身LSN从48推进到70后,返回查询结果。断开连接后,全局一致性开关参数失效。

如果查询业务 SQL 请求等待超时,TaurusDB 的只读节点会向 proxy 返回错误码。此时,proxy 会根据用户配置的超时分发策略,自动将请求发送到主节点(即写节点,确保总是能读到最新的数据),或者向用户返回读失败错误码。

4. 技术实现介绍

内核层整体实现分三个阶段完成

  • fetch阶段

只读节点获取主节点最新flushed to disk lsn

截图4.PNG

图4 获取主机flushed to disk lsn示意

当只读节点启动时,会开启一个常驻线程handle_slave_fetch_lsn。只读节点发起读请求时,采用生产者-消费者模型驱动读业务运行,具体流程如下:

步骤一:

将该读事务搁置到等待队列中,并使用条件通知机制,立即通知handle_slave_fetch_lsn线程,该读事务随即进入条件等待

步骤二:

fetch线程得到事件通知后,立即遍历等待队列列表。如果队列非空,则把等待队列中的事务转移到另一个待通知队列中,并移出等待队列,然后向主机发送获取最新的flushed to disk lsn的消息请求。

步骤三:

当主节点请求响应后,fetch线程遍历待通知列表,并逐个唤醒。只读事务从而退出等待状态,顺利拿到主节点当前最新flushed to disk lsn

步骤四:

只读节点判断获取的flushed to disk lsn是否比上次保存的LSN大。如果变大了,则说明主节点有了新的更新。此时需要等待只读节点推进,进入advance阶段。否则直接返回数据,无需等待只读节点推进。

  • advance阶段

只读节点回放Redo,推进visible lsn到主节点最新flushed to disk lsn。

当只读节点仍落后主节点,即只读事务无法满足立即返回读响应时,则通知handle_slave_sync线程立即获取主机最新的Redo信息进行回放,该读事务会再次进入条件等待状态。

截图5.PNG

只读节点推进流程示意

只读节点Redo回放线程集在完成Redo日志回放后,会更新只读节点的一系列内存数据,同时更新只读节点视图信息,最后唤醒等待中的只读事务。

只读事务会判断只读节点是否已推进到了主机flushed to disk lsn,如果已经完成了推进,则退出等待,否则继续等待。

关键等待流程代码如下:

auto stop_condition_wait_lsn = [&trx, wait_timeout](bool wait) { 
    uint64_t flush_lsn = atm_load(trx->flush_lsn); 
    uint64_t visible_lsn = atm_load(trx_sys->read_consistent_lsn); 
    if (visible_lsn >= flush_lsn) { 
      return true; 
    } 
    if (wait) { 
      auto start_time = trx->start_wait_time; 
      auto now = std::chrono::steady_clock::now(); 
      ulong duration = std::chrono::duration_cast<std::chrono::milliseconds>( 
                           now - start_time).count(); 
      if (duration > wait_timeout) { 
        atm_store(&trx->is_wait_timeout, true); 
        return true; 
      } 
    } 
    return false; 
  }; 
  os_event_wait_for(trx_sys->read_consistent_lsn_event, max_spins, timeout, 
                    stop_condition_wait_lsn);
  • response阶段

只读节点在超时时间内完成推进,并且满足visible_lsn>= flush_lsn,则返回成功。

如果只读节点在超时时间内没有推进到主机的数据,则返回DB_WAIT_LSN_TIMEOUT给proxy层。此时,proxy通过用户配置的consistTimeoutPolicy参数,自动将请求发送到主节点(即写节点,确保总是能读到最新的数据)或者向用户返回读失败错误码。

性能分析

在以下性能测试中,我们使用的实例规格及配置如下:

实例规格:8U32GB

Proxy规格:8个节点*(4U8G)

Proxy路由模式:负载均衡

打开一致性读开关

在不同并发下,sysbench OLTP测试数据(RO只读场景下),如图6所示:

截图6.PNG

只读场景下QPS统计数据

小结:在只读场景下,低并发时,全局一致性QPS相比最终一致性QPS,劣化基本在10%左右,而在高并发下,全局一致性的QPS相比最终一致性QPS ,劣化基本在15%以内。

在不同并发下,sysbench OLTP测试数据(RW读写场景下),如图7所示:

截图7.PNG

读写场景下QPS统计数据

小结:在读写场景下,全局一致性的QPS相比最终一致性QPS ,劣化基本在15%以内。

5. 总结

本文从背景介绍、使用方法、原理介绍以及性能分析等方面,对TaurusDB的全局一致性特性内容做了详细的介绍。该特性在多节点数据库系统的基础上,配合proxy,实现了所有的读操作,无论在哪个节点进行访问,都能看到一致的数据,且性能高效,满足了客户对读请求强一致性的诉求。

[i]数据库代理详细介绍参考:https://support.huaweicloud.com/usermanual-taurusdb/taurusdb_11_0016.html

[ii]一致性介绍参考:https://support.huaweicloud.com/usermanual-taurusdb/taurusdb_11_0041.html

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。