云原生数据库 GaiaDB 的核心技术演进和解析

导读

在越来越强调云原生的环境下,存算分离作为一种新的架构理念,已经是大势所趋。新的技术架构带来新的问题和挑战,百度智能云的云原生数据库 GaiaDB 采用 Quorum 分布式协议、高性能网络、高可靠分布式存储引擎等技术实现更高的性能和可用性。

随着越来越多的企业将业务搬迁至云端,网络、计算和存储资源的弹性伸缩能力变得越来越重要。这些资源的弹性伸缩能力不仅可以帮助云上业务轻松应对业务尖峰,还可以大大降低资源闲置浪费,使得每一分资源都得到充分利用。作为核心基础设施之一,数据库在极致弹性和扩展性方面也进行了多种探索,例如数据的水平分片和分布式化改造。这些方法通过舍弃一部分通用性来增强扩展能力,在配合业务轻度改造的情况下,实现了很显著的体验提升。

然而,作为云上的基础设施,保证用户在迁移前后的业务一致性和可靠性是首要任务。因此,舍弃某些功能或兼容性的路线是无法被接受的。为了解决这个问题,云原生数据库 GaiaDB 应运而生。在保证对原有生态完全兼容的前提下,GaiaDB 使用存算分离技术以及多种内核深度定制优化方案,实现了最大 PB 级数据存储能力与秒级弹性扩缩容能力,使云上业务可以实现全栈弹性伸缩。

GaiaDB 的存算分离架构采用 Quorum 分布式协议、动态实时 MVCC 技术以及用户态高性能网络等技术,这些技术手段的应用对降低访问延迟和提高读写性能有很好的优化效果。此外,该架构不依赖于任何定制化硬件和基础设施,具有较强的通用性和经济性。

下面分别介绍一下 GaiaDB 的技术应用实践。

1. 分布式协议(DB-Quorum)

GaiaDB 基于「Log is database」的设计理念,即数据的修改只写日志,无需刷新脏页,这极大的降低写放大,简化系统 I/O。GaiaDB 针对 I/O 技术栈进行了充分的优化,从演化路径上看,经历了以下几个阶段:

  1. 分布式文件系统 I/O:

GaiaDB 初期存储使用通用的分布式文件系统作为存储底座存储 innodb redo log 和 innodb page。由于分布式文件系统要实现通用的文件一致性语义,其 I/O 提交和 I/O 收割都存在较多的队列调度和保序逻辑,因此其单线程的异步读写吞吐和延迟都离本地盘有较大差距。

  1. 分布式 Raft I/O:

这个阶段,GaiaDB 使用 Raft 三副本进行 redo 日志的持久化,数据页的存储直接使用 peer 三副本持久化到本地文件系统上。日志服务使用 Raft I/O 后,事务写吞吐有了明显提升;但是延时上依然相比本地磁盘性能有较大的gap,特别是长尾问题比较突出。

  1. DB-Quorum I/O:

随着时延敏感业务的增多,对 I/O 的时延的要求进一步提升,GaiaDB 舍弃 Raft 协议,采用 Quorum 读写方案,对 I/O 栈进行极致的性能优化。

下面是从 Quorum I/O 替换 Raft I/O 的主要考量:

单次 Redo Raft I/O 网络和磁盘过高,一次 redo 写 I/O 包含以下流程

a) 主库写 Raft leader;

b) Raft leader 发送 Raft 日志;

c) Raft 日志同步到多数派;

d) Raft 日志 apply,数据持久化到 Log Store;

e) 回复主库。

可以发现其中至少两次网络往返,且无法并行。b) d) 为磁盘写且无法并行。并且由于 RPC 和 Raft 的开销,导致 Redo 持久化的时延显著高于传统单机 MySQL 的本地 Redo 落盘时延。

通过深入分析,我们认为:Raft 协议作为类 Paxos 的分布式协议变种,除了保证分布式副本一致性外,其主要时延其实是提供线性一致性语义的额外代价,而在 GaiaDB 中,我们其实已经把线性一致性的约束拆解到了存储层和事务层:

  1. 存储层,我们已经保证如果 lsn = l 的日志已经持久化成功,那么所有 lsn < l 的日志都已经写成功。

  2. 事务层,我们记录当前完成 I/O 收割的最大 lsn,这个 lsn 之前的写事务都能安全提交。

基于以上两点,Quorum 读写模式已经能较好的满足我们的 Redo I/O 的需求。

Quorum 协议在数据库中需要解决以下问题:

  1. 成员变更:在 Quorum 中管理成员实现较为复杂,Gaiadb 相对优雅地结合了 Raft 和 Quorum 的优点,Raft 管理成员变更等控制流,Quorum 管理数据流。

  2. crash safe: 当计算节点宕机时,Quorum 需要有一个数据对齐的过程,Gaiadb 使用两阶段数据对齐协议, prepare 阶段协商数据持久化一致性位点,commit 阶段进行数据补偿。

GaiaDB 在分布式 Quorum 协议中的优化

为了进一步降低远程 I/O 对性能的影响,GaiaDB 对 I/O 流进行了改造,将核心链路上的同步 I/O 改造为异步 I/O,极大了提升了事务吞吐。

2.高性能智能网络(DB-Network)

在存算分离架构下,网络作为系统 I/O 的重要组成部分,其性能和效率直接影响到整个系统的性能表现。存算分离架构将存储和计算资源分开,使得数据可以在独立的存储节点上进行读写操作,而计算节点则专注于处理计算任务。这种架构的优势在于可以提高系统的扩展性和可靠性,但也增加了网络 I/O 的复杂性和耗时。

在传统的本地 I/O 模式下,数据的读写操作是在本地进行的,因此不需要经过网络传输。而在存算分离架构下,数据的读写操作需要在不同的节点之间进行传输和处理,因此网络 I/O 成为了系统 I/O 中不可或缺的一部分。由于网络传输的耗时相比本地 I/O 要长,因此降低网络 I/O 的耗时成为了存算分离架构必需关注的重点任务之一。

2.1 挑战

GaiaDB 采用了 BRPC 网络框架进行场内通信,但在真实业务场景下,平均耗时为微秒级别(400us-500 us 左右),长尾甚至达到了毫秒级别(10 ms+)。这种情况在某些范围内检索的 SQL 查询中尤为严重,因为这些查询需要远程访问大量的数据,从而导致 I/O 长尾成倍放大 SQL 的整体耗时,容易引发系统故障。

为了保障 GaiaDB 大规模稳定上量,缩短远程 I/O 的长尾和平均时延是至关重要的。通常情况优化远程 I/O 有一下两种手段:

  1. 网络优化:采用更快速的网络设备、优化网络路径、减少网络跳数等措施可以降低网络延迟。

  2. I/O 优化:通过优化数据存储和访问模式,减少 I/O 访问延迟。比如采用更高效的存储介质、缓存技术、并行访问等技术。

2.2 解决方案

GaiaDB 网络优化分为两个部分:

  1. 采用网络超时重定向机制,降低单点访问延迟长尾问题

采取了 BackupRequest 机制,即当一个远程 I/O 请求超时时,系统会重试其他副本,从而有效地抑制了单节点长尾问题。这种机制的应用将远程 I/O 的长尾时延由原来的 10 ms 降低到了 5 ms 以内。通过优化网络架构和采用适当的备份机制,BackupRequest 不仅提高了数据的可用性和可靠性,也大大降低了 I/O 延迟,提高了数据库的整体性能。

  1. 采用高性能智能网络,减少内核态 TCP 与用户态 TCP 的数据拷贝

GaiaDB 引入了百度内部研发的智能网络。智能网络是一种高性能网络框架,它支持内核态 TCP 和用户态 TCP、RDMA 以及百度内部私有协议等多种协议。智能网络能够根据硬件设备的性能和网络状态,自动选择最优的网络协议和参数,从而最大程度地减少网络传输延迟。

智能网络的引入对于降低远程 I/O 的平均时延起到了非常重要的作用。通过智能网络的选择和优化,GaiaDB 能够更好地适应不同的硬件环境,并自动选择最佳的网络协议和参数,进一步提高了数据库的性能和响应速度(E2E 延迟缩短 60%,达到百 us)。

3. 高可靠、高性能分布式存储引擎

存算分离架构是一种现代化的数据库架构设计方式,它的核心思想是将存储和计算分离,以提高系统的可用性、可扩展性和性能。在存算分离架构中,所有需要持久化的数据都被存储在远端的网络附加存储(NAS)、对象存储或分布式文件系统中,或者其他具备高可用能力的分布式存储系统中。而本地存储则只被用来存储临时的、暂态数据,这些数据在需要的时候可以从持久化存储中恢复和重建。

在 GaiaDB 中,「存」所采取的是自研分布式存储系统。该系统结合了 GaiaDB 的数据模型,提供了多版本高可靠高性能的数据存储能力。GaiaDB 的存储系统采用了独特的3副本对等模型,这种模型与传统的 Raft 模型不同。在三副本对等模型中,每个节点都有相同的数据副本,这样可以提高数据的可靠性和可用性。由于没有主从节点的概念,每个节点都可以独立地提供读写服务,从而避免了单点故障的问题。此外,由于对等性,每个节点都可以同时提供 I/O 服务,从而提高了系统的整体性能。

3.1 挑战

存算分离架构为 GaiaDB 带来了新的挑战。在早期阶段,GaiaDB 使用容器模型来存储单副本,并将三个副本部署在不同的容器节点上。然而,由于实测时多跳网络等因素的影响,I/O 性能无法满足要求。为了解决这个问题, GaiaDB 采用了容器+本地磁盘架构模型,虽然满足了 I/O 时延需求,但也带来了新的问题。

  1. 成本问题逐渐显现。在存算分离架构下,需要处理突发流量但又无法共享资源,这容易导致资源浪费和成本上升。例如,每个容器节点分配了 4G 内存作为数据库的一个副本,这无疑增加了系统的整体成本。

  2. 管理问题也是个大问题。当处理的实例数量达到成千上万级别时,容器调度和资源分配等难度上升,实例扩容等耗时也变得更长。例如,每个节点上的端口数量、监控数量以及副本容灾分布规划等都需要大量的人力和物力来管理。

  3. 故障问题也是一个不可忽视的问题。在存算分离架构下,当磁盘或机器出现故障时,数据恢复存在调度管理问题。例如,恢复限速、排队等缺乏全局管理能力,容易造成热点,导致无法提供服务。

3.2 解决方案

为了解决在容器化环境中面临的存储问题,GaiaDB 采用了自主研发的分布式多租户存储方案。该方案不仅在架构上支持多租户模式,还实现了对资源的极大化利用。

GaiaDB 的分布式多租户存储方案将多个集群的数据统一存储在一个系统中。通过资源的闲置调度策略,该方案能够有效地利用存储资源,提高存储空间的利用率。同时,GaiaDB 还对副本管理进行了优化。该方案可根据实例规模、集群磁盘使用率、集群机器负载、集群机架位和集群机器所在交换机等因素进行管理,使存储资源得到充分利用,并满足高性能的存储需求。

然而,随着时间的推移和集群的扩容或缩容等操作,存储系统中的副本分布可能会出现不均衡的现象。为了解决这一问题,GaiaDB 的分布式多租户存储方案能够提供统一的资源均衡策略。这种策略可以在一段时间后自动调整副本的位置,使副本分布更加合理,达到最优的存储效果。

另外,GaiaDB 的分布式多租户存储方案还具备强大的故障恢复能力。当故障发生时,该方案能够实现统一的自动恢复管理。根据待恢复的副本数量等因素,该方案能够合理地分配集群资源,减少资源堆积等问题。这种设计可以在保证数据安全的同时,最大程度地降低存储系统的维护成本,提高系统的可用性和稳定性。

4. 多地多活技术

对于高可用性需求的业务,多可用区部署和多地域部署是常见的解决方案来确保数据库的高可用性。多可用区部署是在多个可用区中复制和备份数据,以避免一个可用区故障导致服务中断,但需考虑数据一致性和同步问题,以及更高的资源和成本。多地域部署是在不同地域的机房中复制和备份数据,网络延迟更大,数据存在秒级别延迟。

4.1 挑战

数据库在多机房和多地域部署的挑战主要来自于数据的一致性、可靠性和延迟问题。以下是对这些挑战的描述:

  1. 数据一致性:在多机房和多地域部署的情况下,保持数据一致性是一个主要挑战。当多个节点在分布式系统中处理数据时,可能会出现数据一致性问题。这种一致性问题通常由网络延迟、系统故障和数据复制延迟等因素引起。为了解决这个问题,可以使用一些技术手段,如分布式事务、一致性保证协议等。

  2. 数据可靠性:在多机房和多地域部署的情况下,数据可靠性是一个重要的挑战。由于地理位置的分散,数据在传输和处理过程中可能会出现更多的错误或丢失的风险。为了提高数据可靠性,可以使用冗余数据复制、分布式数据备份等技术。

  3. 延迟问题:在多机房和多地域部署的情况下,由于地理位置的分散,网络延迟可能会成为一个主要的问题。随着距离的增加,网络延迟会增加,这可能会影响数据库操作的性能和响应时间。为了降低延迟,可以采取一些措施,如优化网络架构、使用低延迟网络协议和缓存技术等。

4.2 解决方案

在数据库多 AZ 的部署中,我们采用了物理同步协议,这种协议可以确保在任意切换过程中不丢失任何数据。通过多 AZ 热活的解决方案,我们可以同时提供服务,从而确保即使在一个区域发生故障时,其他区域也能够继续提供服务。

为了实现低延迟和平滑兼容慢节点的目标,我们采用了就近访问的策略。这个策略能够让用户在访问数据库时自动选择最接近他们的节点,从而最大程度地减少延迟。同时,我们还不断优化数据库的操作和查询,以确保即使在慢节点上也能够平滑地兼容。

在多可用区部署时,GaiaDB 模块的自适应就近访问策略可以感知元数据的变化,并根据这些变化及时切换访问路线。这种策略可以有效地应对各种故障和异常情况,确保数据的可靠性和可用性。

在多地域部署时,GaiaDB 的自研同步组件 Replicator 通过同步 Redo 流来支持 DDL 操作等高级功能。这种方案可以实现主从地域之间的时延小于 2 秒,从而确保数据的实时性和一致性。同时,这种方案还具有良好的可扩展性和灵活性,可以轻松地适应不同地域的需求和变化。

总结

存算分离已成为流行的架构理念,通过存算分离可以提高数据库的弹性能力,降低存储成本、提高可用性。GaiaDB 在架构演进中采用 Quorum 分布式协议和高性能网络技术降低计算和存储之间的访问延迟,提高并发访问性能;通过高可靠的分布式存储引擎实现 RPO=0,同时利用分布式存储的扩展性提升 I/O 带宽和并发性能。

相关推荐
乌鸦乌鸦你的小虎牙1 小时前
qt 5.12.8 配置报错(交叉编译环境)
开发语言·数据库·qt
一只大袋鼠2 小时前
Redis 安装+基于短信验证码登录功能的完整实现
java·开发语言·数据库·redis·缓存·学习笔记
Anastasiozzzz2 小时前
深入研究Redis的ZSet底层数据结构:从 Ziplist 的级联更新到 Listpack 的完美救场
数据结构·数据库·redis
菠萝蚊鸭2 小时前
x86 平台使用 buildx 基于源码构建 MySQL Wsrep 5.7.44 镜像
数据库·mysql·galera·wsrep
沙漏无语4 小时前
(二)TIDB搭建正式集群
linux·数据库·tidb
姚不倒5 小时前
三节点 TiDB 集群部署与负载均衡搭建实战
运维·数据库·分布式·负载均衡·tidb
小二·5 小时前
Go 语言系统编程与云原生开发实战(第38篇)
网络·云原生·golang
隔壁小邓5 小时前
批量更新方式与对比
数据库
数据知道5 小时前
MongoDB复制集架构原理:Primary、Secondary 与 Arbiter 的角色分工
数据库·mongodb·架构
人道领域5 小时前
苍穹外卖:菜品新增功能全流程解析
数据库·后端·状态模式