使用 Amazon Aurora 全球数据库的写转发功能进行 PostgreSQL 数据库博客

在 Amazon Aurora 全球数据库中使用写转发功能

关键要点

Amazon Aurora Global Database 支持写转发功能,使开发者能够通过辅助区域直接向主区域发送数据修改请求。此功能简化了跨区域的写入流程,减少了对网络配置和一致性管理的需求。写转发功能支持多种一致性模式,帮助用户在一致性和性能之间取得平衡。

Amazon Aurora 结合了传统企业数据库的性能与可用性,同时具有开源数据库的简单性和成本效益。作为一项全球规模的关系型数据库服务,Amazon Aurora 具备与 MySQL 和 PostgreSQL 的兼容性。使用 Amazon Aurora Global Database 服务,用户可以将 Aurora 数据库跨多个 AWS 区域,确保在区域故障时迅速恢复,通常只需一分钟。此外,该服务还提供低延迟读取,改善应用程序的读取查询响应速度。

每个 Amazon Aurora 全球数据库都有一个主要区域和最多五个辅助区域。主要区域负责读写操作,而辅助区域仅提供读取服务。2023年11月9日,Aurora Global Database for PostgreSQL宣布支持写转发功能,将这一特性扩展至 Amazon Aurora 的 MySQL 兼容版和 PostgreSQL 兼容版数据库。写转发功能允许开发者在辅助区域的读取节点上发出数据操作命令,并将其转发到主要区域。当写入操作被转发后,首先会在主要区域应用更新,然后再复制到辅助区域。此机制确保主要集群始终是数据的权威来源,并且拥有数据的最新副本。通过全球写转发,开发者不再需要设置区域间的网络连接来支持跨区域写入操作。此外,开发者可以根据需求指定一致性级别,执行写完后的读取操作。

在本文中,我们将演示如何在 PostgreSQL 的 Aurora Global Database 中启用并使用写转发功能,涉及多种一致性模式。

全球写转发概述

当应用程序使用全球数据库的辅助区域为用户提供快速、就近的读取服务时,偶尔也需要向数据库写入内容。传统上,实现跨区域写入的步骤包含:

建立辅助区域与主要区域的连接。将应用程序的读取和写入请求进行分离,确保读取请求发送到辅助区域,写入请求发送到主要区域。在应用程序中实现自定义逻辑,以管理写后读取的一致性。Amazon Aurora Global Database 在区域间异步复制数据,通常延迟在毫秒级。尽管复制延迟很小,但仍然可能导致读取请求在辅助区域的写入请求在复制到辅助区域之前未被捕获。

全球写转发的优势

在 Aurora Global Database for PostgreSQL 中的 写转发功能 解决了上述挑战,减轻了开发者的负担。使用全球写转发,应用程序可以连接到辅助区域的读取节点,并同时发出读取和写入请求。读取请求直接由辅助区域的节点响应,而写入请求则会自动转发至主要区域,在主要区域先进行更新,然后再将更改复制到辅助区域。写转发的主要优势包括:

管理连接 写入请求被透明地转发到主集群,Aurora 负责维护活动和管理辅助区域与主要区域之间的连接。无复制冲突 所有写入操作由主集群的单一写入节点应用,因此无复制相关的更新冲突。简化操作 不需要在应用程序中分割读取和写入请求,也无需构建复杂的逻辑来管理写后的读取一致性。灵活性 可以选择几种不同的读取一致性级别,以满足应用程序的不同需求,在一致性与性能之间进行良好的权衡。

全球写转发的工作原理

Aurora Global Database 的写转发通过在辅助区的读取副本中接受写入语句来实现。Aurora 将识别出的写入语句与必要的上下文转发至主集群。语句的输出包括警告和错误将返回给辅助区域的读取实例,再返回给应用程序。整个过程对应用程序是透明的。只需为集群启用写转发,并确保为应用程序设置适当的一致性模式。Aurora Global Database for PostgreSQL 的一致性模式通过 apgwriteforwardconsistencymode 参数进行管理,您还可以通过在单个会话中设置 apgwriteforwardconsistencymode 变量来覆盖该参数。

接下来,我们将讨论 Aurora Global Database for PostgreSQL 中可用的各种一致性模式。

一致性模式

如前所述,写入转发至主集群后,复制回辅助数据库集群需要一些时间。如果您不需要写后读取的一致性,则可以直接继续到下一个语句,而不必等待复制完成,从而改善读取延迟。然而,如果您的应用程序要求写后读取的一致性,则必须等待复制完成,以确保后续读取可以看到最新的写入。为此,写转发支持以下可配置的读取 一致性模式:

最终模式 最终一致性模式意味着随后读取请求不会等待写入复制完成。当您需要从辅助区域执行写入时,如果不希望麻烦地设置区域间的网络连接,并且应用程序不需要在写后读取场景中保持一致性,则可以使用最终一致性模式。会话模式 会话一致性模式确保在同一会话中的写入后读取将等待复制完成才会处理读取查询。这是 apgwriteforwardconsistencymode 参数的默认值。这确保会话能够见到自己的更改,但不保证其能见到其他会话发出的更改。全局模式 全局一致性模式确保读取查询等待复制跟上读取请求开始时的时间点。这意味着来自辅助集群的读取将看到在主集群中提交的更改,直到读取查询在辅助集群中开始为止。虽然此模式提供了最强的一致性,但会影响性能。关闭模式 关闭一致性模式将禁用写转发。您可以通过参数组禁用写转发,或在单个会话中间歇性地使用 apgwriteforwardconsistencymode 变量进行设置。通过禁用参数组中的写转发,确保开发者在需要使用时必须指定最符合应用需求的一致性模式。

apgwriteforwardconsistencymode 参数的默认值是 session。

在 Aurora 全球数据库中启用写转发

您可以在向现有 Aurora 集群添加新区域时启用写转发,也可以修改现有的 Aurora 全球数据库。启用写转发时,现有 Aurora 全球数据库集群无需重启。要在现有的 Amazon Aurora Global Database for PostgreSQL 中启用写转发,请按照以下步骤操作:

在 Amazon RDS 控制台中,选择导航窗格中的 Databases。选择 Aurora Global Database 的辅助集群,然后点击 Modify。在 Read replica write forwarding 部分,选中 Turn on read replica write forwarding,然后点击 Continue。对于 Schedule modifications,选择 Apply immediately,以便修改尽快生效,而不必等待数据库集群的维护窗口设置。

如果不希望立即应用修改,可以选择 Apply during the next scheduled maintenance window,以在即将到来的维护窗口中启用写转发功能。在启用写转发时,不会对主或辅助全球数据库集群发生重启或不可用的情况。

使用写转发

为了演示写转发功能,我们创建了一个版本为 154 的 PostgreSQL Aurora Global Database,主要区域位于 apsouth1,辅助区域位于 euwest1。有关写转发特性的区域和版本可用性,请参考 Aurora PostgreSQL 中写转发的区域和版本可用性。请按照以下步骤使用写转发功能:

在连接到主要区域的写节点使用集群入口点后,使用以下代码创建新表 logins:

sqlpgtest =gt CREATE TABLE logins( id serial primary key name varchar(100) not null loginDate timestamp)

注意,写转发功能仅转发 DML 命令,这意味着诸如 CREATE TABLE 的 DDL 命令必须直接在主要区域中执行。要更好地理解哪些语句与写转发功能兼容,请参阅 与写转发兼容的应用程序和 SQL。有关写转发功能中的隔离和一致性模式的考虑,请参考 Aurora PostgreSQL 中的写转发隔离和一致性。

从辅助区域 (euwest1) 通过辅助区域的读取入口点进行连接。在继续之前,使用以下命令检查 apgwriteforwardconsistencymode 参数在参数组中设置的一致性级别:

sql/检查 apgwriteforwardconsistencymode 的一致性模式/

pgtest =gt SHOW apgwriteforwardconsistencymodeapgwriteforwardconsistencymode

session(1 row)

该参数值由数据库集群参数组派生于所有会话。apgwriteforwardconsistencymode 参数的默认值是 session。如果需要,您可以在会话中设置所需的参数值以覆盖集群参数组中设置的值。修改 apgwriteforwardconsistencymode 参数值不需要重启数据库实例。

在辅助区域 (euwest1) 中对 logins 表发出 DML 命令插入新记录。启用写转发功能后,观察以下 DML 语句如何从辅助区域插入一行到 logins 表中:

sql/ 从辅助区域转发的写入并读取 logins 表中的行 /

飞鸟加速npv官网

pgtest =gt insert into logins values (default John login from Dublin (secondary)110523)

INSERT 0 1

我们可以通过读取 logins 表中的所有行来验证写转发功能是否成功:

使用 Amazon Aurora 全球数据库的写转发功能进行 PostgreSQL 数据库博客

sqlpgtest =gt select from logins order by id descid name logindate 2 John login from Dublin (secondary) 20231105 000000 1 Adam login from Mumbai (primary) 20231004 000000

根据上面的输出,可以看到当您对辅助读取全局数据库集群发出 DML 命令时,Aurora 将 DMLINSERT语句从辅助读取区域转发到主要区域的写入节点。数据将复制回辅助区域,并随后从辅助区域的读取节点可见。

现在我们已经验证了 Amazon Aurora PostgreSQL 全球数据库中的写转发功能,接下来让我们看看在不同一致性模式如最终、一致会话和全局模式下,写转发功能是如何工作的。为此,我们使用了一个基本的 Python 应用程序。Python 应用程序向辅助区域的读取节点发出写请求插入 logins 表的记录。在提交写请求之后,应用程序读取并显示 logins 表中的最新五条记录。

最终一致性模式

让我们开始通过编辑参数组中的 apgwriteforwardconsistencymode 参数值,将一致性模式设置为 eventual。

保存更改后,您可以使用 SHOW 命令验证一致性模式与前面步骤类似,确认参数值更改已在辅助区域生效。

为了演示最终一致性,Python 应用程序中启动了一个单线程。在线程中,在辅助区域的读取入口点上发出 INSERT 命令。写入完成后,读取 logins 表中的最新五行数据。

在启动应用程序之前,让我们验证辅助区域的副本延迟。复制延迟能够给我们一个提示,表明主要区域apsouth1中提交的写入需要多长时间才能在辅助区域euwest1中可用。将使用 AuroraReplicaLag 实例级别 Amazon CloudWatch 指标来监视副本延迟。有关 Aurora 其他 CloudWatch 指标的更多信息,请参见 Amazon Aurora 的 CloudWatch 指标。

在我们的案例中,在辅助区域观察到的 5 分钟内平均的 AuroraReplicaLag 为 28597 毫秒。由于我们使用的是最终一致性模式,Aurora Global Database 不会等待写入在辅助区域复制完成。因此,只要应用程序的读取请求在大约 200 毫秒之前到达,就不会在读取请求的输出中看到转发的写入。让我们看看实际表现如何:

bash/ 测试 eventual 一致性,通过单一线程发出写后读取请求 /

[ec2user@] python39 demowriteforwardingpy 1[Thread thread1] Starting thread1 with args [demowriteforwardingpy1][Thread thread1] Write committed at time 11/06 62303519 with login user ligiro[Thread thread1] Reading latest 5 row from login table at 11/06 62303537 ID Login Detail Login Date 2 John login from Dublin (secondary) 20231105 000000 1 Adam login from Mumbai (primary) 20231004 000000 [Thread thread1] [start 11/06 62302481 end 11/06 62303539 timeLapse 10587]

如预期所示,使用写转发功能的最终一致性模式时,即使用户 ligiro 的写入操作已经提交,但在随后的读取请求中尚未可见。造成该现象的原因是辅助区域的副本尚未赶上。

会话一致性模式

接下来,我们使用会话一致性模式运行相同的测试。但在重新运行应用程序之前,让我们将 apgwriteforwardconsistencymode 参数值更新为 session,并确认辅助区域中的参数值已更新。当我们再次运行相同的 Python 应用程序时,将产生以下结果:

bash/ 测试 session 一致性,通过单个线程发出写后读取请求 /

[ec2user@] python39 demowriteforwardingpy 1[Thread thread1] Starting thread1 with args [demowriteforwardingpy 1][Thread thread1] Write committed at time 11/06 63129776 with login user poqohi[Thread thread1] Reading latest 5 row from login table at 11/06 63129795 ID Login Detail Login Date 4 poqohi login from Dublin (secondary) 20231106 063128750334 3 ligiro login from Dublin (secondary) 20231106 062302481080