深入了解 Google 的 AlloyDB PostgreSQL 架构
[
](https://res.cloudinary.com/practicaldev/image/fetch/s--2RSUZ1B2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https: //www.dragonsegg.xyz/content/images/2022/05/google-alloydb-architecture-deep-dive.jpeg)
**今年Google I/O上最激动人心的公告之一是AlloyDB for PostgreSQL的预览版,它是 Google Cloud 上完全托管的、与 PostgreSQL 兼容的数据库服务。
AlloyDB 团队对他们的服务提出了大胆的主张:
-
与标准 PostgreSQL 相比,AlloyDB 对事务性工作负载快 4 倍以上,对分析性工作负载最高 100 倍。
-
与 Amazon 的服务相比(他们没有说,但我们可以猜测是 Aurora 🤔),AlloyDB 2 倍于事务性工作负载。
这些令人印象深刻的数字!
AlloyDB 开发人员如何能够为事务和分析工作负载实现这种加速?为了实现这一目标,需要哪些架构创新?是否有类似云规模分布式系统的架构师和开发人员需要学习的经验教训?
在这篇文章中,我将向您介绍 AlloyDB for PostgreSQL 的架构和设计细节,特别关注其存储引擎,这是这些性能数据背后的秘密武器,也是许多行政和管理优势的催化剂的服务。
让我们开始吧,好吗?
AlloyDB 服务说明和好处
在我们深入探讨 AlloyDB 架构的设计选择、权衡和成本影响的有趣兔子洞之前,让我们简要地戴上我们的产品管理帽子🧢,定义什么是 AlloyDB,并阐明企业如何期望从中受益.这将有助于为其余讨论设置上下文。
首先,AlloyDB 是一个与 PostgreSQL 兼容的数据库。至少在理论上,这意味着客户可以简单地将数据从他们现有的 PostgreSQL 数据库迁移到 AlloyDB,在他们的应用程序中更新数据库连接字符串以指向 AlloyDB 实例,这一切都可以正常工作!这很好,因为它简化了客户心目中的采用过程。
顺便说一句:
请注意现在各种数据库都与 PostgreSQL 兼容。在我看来,这是一个令人兴奋的趋势!在很长一段时间内,由于缺乏协议和语法标准化,应用程序世界陷入瘫痪。 PostgreSQL、MySQL 和其他数据库在表面上看起来很相似,但在它们使用的客户端-服务器协议或它们支持的 SQL 语法方面却是天壤之别。很高兴看到 CockroachDB、Redshift、Aurora 和现在的 AlloyDB 都在 PostgreSQL 上融合。这将大大简化驱动程序开发、应用程序编码以及安全性和可观察性工具!
图 1 显示了 AlloyDB 的高级功能组件。
[
](https://res.cloudinary.com/practicaldev/image/fetch/s--ktRDEEK1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https: //www.dragonsegg.xyz/content/images/2022/05/image-9.png)
图 1:AlloyDB 高级架构
我们如何描述这项服务?
-
首先,AlloyDB 是一个区域服务(想想 AWS 术语中的
us-east-1、us-west-1等),也就是说它不是多区域。 -
其次,在一个区域内,出于冗余和可用性的原因,AlloyDB 跨多个可用区 (AZ) 或数据中心运行。因此,它是多区域的。
-
最后,该服务包含多个应用程序可以连接的计算实例。有用于服务读取和写入操作的单例主实例。然后,有多个副本实例用于仅服务于读取操作。副本实例_不_服务写入操作。值得注意的是,如果现有的主实例由于某种原因而死亡,多可用区设置允许将副本提升为主状态。
此外,由于 AlloyDB 是一个完全托管的服务,服务器管理、修补、数据保护和复制都被卸载到云提供商。
这些运营和管理优势,再加上 AlloyDB 的性能和可扩展性属性,将使 AlloyDB 成为可能希望迁移到云的企业的引人注目的产品。
现在 PM-speak 已经结束,让我们深入了解架构细节。
单体数据库设计限制
这里有一个需要思考的问题:
上面的图 1 有什么地方让您觉得奇怪吗?
如果您研究过标准 PostgreSQL 或 MySQL 数据库的体系结构,您就会知道它们的设计本质上是_monolithic_。这意味着数据库在单个节点或机器上运行,计算 (CPU) 和存储 (磁盘) 都在其上并置。
这样的数据库有一个基本但有据可查的设计问题。由于计算和存储之间的强耦合,随着数据量的增加,不能随意不断地向机器添加更多磁盘。同样,随着工作负载数量或多样性的增加,不能简单地添加更多计算 (CPU),除非通过重新配置机器。
通常,唯一的解决方案是扩大规模,即切换到越来越强大的机器。这既昂贵又自然受到摩尔定律的限制。由于这些原因,这些单体设计在数据量或工作负载的云规模上运行并不常见。
这就是AlloyDB创新和架构差异化的症结所在,AlloyDB团队称之为_Disaggregation of Compute and Storage_!
另一个快速的旁白:
“解耦”这个词看起来很花哨,但它确实是其他数据仓库社区所说的“解耦”,这个概念已经存在了十多年。 Snowflake 是最早的产品之一,其架构建立在计算与存储分离的基础上,它通过将数据存储在 S3 存储桶中并在 EC2 实例上运行数据库引擎来实现。
计算与存储的这种解耦或分解意味着什么,它提供了哪些好处?
对于运行关键业务事务或分析工作负载的数据库系统,能够独立扩展计算和存储非常重要。无法做到这一点会导致一系列大规模的运营和管理挑战:
-
计算资源无法在不影响存储的情况下动态适应不同并发工作负载的需求,反之亦然。
-
工作负载在此类架构上运行时会相互干扰,因为它们都在争夺相同的共享资源。这会导致整体性能不可预测。
-
在多节点主副本设置中,主实例和副本实例之间的数据复制存在相当大的滞后。根据数据库负载,故障转移时间可能最终会比可接受的更长,而且更难以预测。
将计算与存储分离可以解决或减轻许多这些限制。它允许根据数据库中运行的每个工作负载来配置和扩展计算,而不会影响存储或其他工作负载的性能。
需要时,可以动态启动较新的只读副本以提高读取工作负载的性能。通过主副本和副本之间的高效复制,可以改进故障转移时间并使其更加可预测。
然而,这一切是如何实现的?答案在于AlloyDB的存储子系统的设计。接下来让我们看看吧!
AlloyDB存储层组件
下面的图 2 从图 1 中打开了 AlloyDB 的存储层以显示其组件。
[
](https://res.cloudinary.com/practicaldev/image/fetch/s--lovf7pHj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https: //www.dragonsegg.xyz/content/images/2022/05/image-10.png)
图2:AlloyDB存储层组件
存储层有三大服务:
-
日志存储服务:用于快速写入 WAL(预写日志)记录的低延迟服务。
-
日志处理服务:异步处理WAL记录,生成物化的最新数据块。
-
块存储服务:跨可用区域持久存储数据块以实现容错,并支持分片。
您可能想知道 WAL 是什么以及它与数据块有何不同。想象一下银行应用程序中的一个Balances数据库表。帐户上的每笔贷记或借记交易都会更新帐户的余额。然而,在存储层,由于与故障处理、恢复和性能有关的多种原因,数据永远不会就地更新。相反,数据库通常会“预写”或附加到日志文件中,每个提交的事务的详细信息。
写入 WAL 的事务详细信息示例包括语句类型(INSERT、UPDATE、DELETE)、受影响的表列、新数据值等。
WAL 还有一个额外的好处,那就是数据库的写入行为被强制为严格的仅追加,从而在存储层获得良好的性能,它擅长处理追加(也称为流式写入),远优于随机写入。
因此,我们的银行应用程序将为每笔成功的贷记或借记交易附加一条新记录到 WAL。显然,这就引出了一个问题,如何为读取提供服务?为了保持读取的快速和快速,一个称为“日志重放”的过程通过按时间顺序重放 WAL 记录来重构数据,并将它们作为块存储在数据库中。
因此,我们可以认为数据块是数据库的最新状态,而 WAL 是数据库所经历的所有状态转换的记录。
有了这个上下文,现在让我们重新审视一下图 2 中每个存储组件的职责:
-
日志存储服务负责管理 WAL,并保持写入的快速和快速。
-
_日志处理服务_负责重放WAL记录以创建数据块的最新快照,并将它们发送到块存储服务。它还负责在读取期间根据需要将这些数据块提供给主数据库实例和副本数据库实例。
-
_块存储服务_负责确保数据块在本地及时可靠地持久化,并在区域范围内的所有区域中复制。它还会在需要时为 log processing service 提供相关数据块。
顺便说一句,要记住的一个重要细节是整个存储子系统是_多分区_。这意味着每个服务至少有一个实例在该区域内的每个可用区域中运行,以实现高可用性和容错。
所以,是的,我们已经将计算与存储分离,并在此过程中增加了大量的复杂性! 🤯
然而,为了什么目的?这种架构有什么好处?
-
由于解耦,可以单独扩展服务以适应增加的需求。例如,即使 log processing service 显示为单例,它的多个实例也可以在每个可用区域内动态启动以加速 WAL 处理,或者以更高的吞吐量为数据密集型工作负载提供数据块。类似地,_block storage service_可以扩展以满足持久性和可靠性的需求。
-
数据复制和数据备份等任务可以完全委托给存储层,而不会影响计算实例(其功能纯粹是查询优化和执行引擎)。
-
新副本创建和故障恢复操作速度加快,因为:a) 最新数据块已经可用(已从 WAL 重建),b) 可以从任何可用区读取数据块,无论是基础设施故障还是区域故障。
AlloyDB 写入处理
我们现在将再次双击 AlloyDB 的架构来检查它是如何处理写入的。
图 3 本质上是图 2 的复制品,其中删除了读取路径,因此我们可以只关注写入路径。
[
](https://res.cloudinary.com/practicaldev/image/fetch/s--N81B2t2H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https: //www.dragonsegg.xyz/content/images/2022/05/image-15.png)
图 3:AlloyDB 写入处理
当客户端应用程序想要发出写入(例如 INSERT、UPDATE 或 DELETE 语句)时,它必须始终针对主实例执行此操作,因为副本实例仅服务于读取。
当主实例收到写入时,它会在成功执行语句和事务提交后将新记录附加到 WAL(正如我之前解释的那样)。一旦_日志存储服务_确认 WAL 记录已被持久保存,主实例就会响应客户端应用程序以指示其写入成功。
同时,主实例还将 WAL 记录传输给所有活动副本,以便它们可以更新各自的内部状态。这是写入工作流程中的关键步骤,否则副本可能会很快与主副本不同步,并开始向客户端提供陈旧数据。
log 处理服务 异步消费新写入的 WAL 记录,在相关数据块的当前状态上重放它们,并将它们持久化到底层存储服务。
当然,还有许多与 MVCC 和 ACID 语义相关的血腥实现细节。尽管如此,这仍将是处理写入的底层内容的公平和准确的高级表示。
AlloyDB 读取处理
接下来,我们将看看 AlloyDB 的架构流程是如何读取的。
下面的图 4 显示了读取的数据路径,类似于上面的图 3 显示专门的写入路径。
[
](https://res.cloudinary.com/practicaldev/image/fetch/s--8ehnj4ux--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https: //www.dragonsegg.xyz/content/images/2022/05/image-16.png)
图 3:AlloyDB 读取处理
与写入不同,客户端应用程序可以自由连接到任何实例以发出读取操作(例如 SELECT 语句)。然而,有点令人惊讶的是,读取的处理比写入的处理要复杂得多。
顺便说一句,一直以来,当我们颂扬将计算与存储分离的优点时,我们并没有提出它明显但不受欢迎的副作用。当计算和存储解耦时,由于计算和存储服务之间的额外网络跃点、传输协议开销等原因,读写吞吐量会受到影响。
为了弥补这些新的开销,所有基于计算存储解耦概念的架构都采用激进的缓存策略,有时在多个层上,以提高读取性能。
AlloyDB 也不例外!如图 4 所示,除了数据库自己的缓冲区缓存之外,AlloyDB 架构师还在计算实例中添加了他们所谓的“超高速缓存”。这是为了扩展工作集的大小,并减轻由于丢失数据块导致的网络往返造成的任何减速。
同样值得注意的是,丢失的数据块是从_日志处理服务_获取的,而不是从_块存储服务_获取的。 日志处理服务,除了具备处理WAL的能力外,还支持PostgreSQL的buffer cache接口。它这样做是为了缓存来自_block storage service_的数据块,并将它们提供给主实例和副本实例。因此,_日志处理服务_有效地成为架构中的另一个缓存层。
用微处理器缓存做一个非常粗略的类比(向纯粹主义者道歉😜):
-
将主/副本实例中的缓冲区缓存视为 L1 缓存
-
将超高速缓存视为二级缓存
-
将_日志处理服务_缓冲区缓存视为L3缓存
明白了吗?
AlloyDB 架构中采用的缓存策略非常慷慨和激进。仅这一点,再加上多个副本实例提供的并行性,很可能是 AlloyDB 预览公告中引用的令人印象深刻的性能数字的原因。
正如您必须正确思考的那样,这将对供应和运营成本产生相当大的影响!但是,希望迁移到云以获取好处的企业可能不会介意支付!
So,我们查看了 AlloyDB 的架构,以了解它如何将计算实例与存储层分离/解耦,以及它如何处理读取和写入。我们检查了为确保读写保持高性能而做出的设计选择,尽管采用了解耦架构。与标准 PostgreSQL 和 Amazon 的 Aurora 相比,AlloyDB 大量使用缓存,这解释了事务和分析工作负载的令人印象深刻的性能数字。
AlloyDB 似乎设计得非常好,我非常喜欢它!祝贺他们的工程团队!请务必在 Google Cloud 上查看该服务!
参考文献
1.AlloyDB for PostgreSQL 简介:从昂贵的遗留数据库中解脱出来
2.AlloyDB for PostgreSQL 底层:智能、数据库感知存储
更多推荐
所有评论(0)