【译文】我们如何在 11 秒停机时间内迁移 PostgreSQL 数据库

GOV.UK Notify GOV.UK 平台即服务 (PaaS) 托管。PaaS 即将退役,因此我们正在将所有基础设施迁移到自己的亚马逊网络服务(AWS)账户中。这篇博文介绍了我们如何在停机时间最短的情况下迁移 PostgreSQL 数据库。

迁移我们的数据库

PaaS 为我们提供了一个数据库,我们用它来存储我们的所有数据–从我们发送的每个通知的数据到服务团队用来发送这些通知的成千上万个模板的内容。这是一个 AWS RDS PostgreSQL 数据库,位于 PaaS 的 AWS 账户中。我们在 PaaS 中运行的应用程序与该数据库会话。我们将这个数据库称为 “源数据库”。

我们需要在自己的 AWS 账户中建立一个新数据库,并让我们的所有应用程序都与新数据库会话。我们将把这个新数据库称为 “目标数据库”。

在我们自己的 AWS 账户中创建一个新的 PostgreSQL 数据库并不难。难的是转移我们的所有数据,并让我们的应用程序使用这个新数据库,同时尽量减少停机时间。

关于源数据库的更多信息

我们的源数据库大小约为 400GB。它有大约 13 亿行、85 个表、185 个索引和 120 个外键。数据库版本为 PostgreSQL 11。

平日里,我们每秒进行大约 1000 次插入或更新(有时低得多,有时高得多),以及类似数量的读取。

GOV.UK Notify 每天要发送数百万个重要而及时的通知,从洪水警报到更新用户的护照申请信息。我们发送的每一条通知都需要与我们的数据库会话。因此,我们必须尽可能减少停机时间。

AWS 数据库迁移服务

PaaS 团队为我们提供了使用 AWS 数据库迁移服务(DMS)迁移数据库的功能。

DMS 负责将数据从源数据库传输到目标数据库。它可以在源或目标 AWS 账户中运行。

DMS 的工作原理如下

  1. 逐表复制截至特定时间点的所有数据。这被称为 “满载 “任务。
  2. 进入复制模式,确保将源数据库上的所有新事务重放至目标数据库,从而使两个数据库保持同步。

然后,我们将负责让应用程序停止与源数据库会话,并开始与目标数据库会话。

数据库迁移过程

数据库迁移过程分几个阶段完成。

设置 DMS 实例

在我们的案例中,DMS 实例是在源 AWS 账户中创建的。我们之所以选择源账户,是因为 PaaS 团队已经在其账户中设置了 DMS 实例,因此能够快速、轻松地完成这项工作。

DMS 实例还需要获得 PostgreSQL 凭据,以便与源数据库和目标数据库会话。

DMS 实例和目标数据库位于不同的虚拟私有云(VPC)中。在 PaaS 团队的帮助下,我们建立了 VPC 对等关系,这样来自 PaaS VPC 中 DMS 实例的流量就可以直接路由到我们的 VPC,而无需通过公共互联网。

设置目标数据库

我们在自己的 AWS 账户中创建了目标 RDS 实例。PostgresSQL 11 版本即将不支持,因此我们借此机会升级了 PostgreSQL 版本,将新数据库设为 PostgreSQL 15。

然后,我们使用 `pg_dump` 对源数据库的数据库模式进行转储。这样,我们就得到了一个包含 SQL 命令的文件,可以重新创建数据库模式。

从数据库模式中,我们提取了表的声明,并将其应用到目标数据库中。

此时我们没有应用外键,因为 DMS 的完全加载过程不会按照外键约束的顺序复制数据。

此时我们没有创建主键或索引,因为这会大大降低完全加载任务的速度。每次插入都会花费更长的时间;它需要更新我们的索引,当插入数十亿行时,这将增加大量的时间。首先复制所有数据,然后再添加索引要快得多。

完全加载

在创建了带表的目标数据库后,我们开始执行 DMS 完全加载任务。这将复制我们按下 “开始完全加载 “按钮时存在的所有数据。在此之后,它不会复制任何新数据或更新。完全加载任务大约需要 6 个小时才能完成。

完全加载任务完成后,我们应用了源数据库模式文件的剩余部分,其中添加了索引和关键约束。添加这些内容花费了大约 3 个小时。

复制

当我们的完全加载任务完成后,目标数据库中的数据与开始完全加载任务时源数据库中的数据一致。但在此之后,我们的源数据库中又发生了许多新的插入、更新和删除。而且还会有更多的变化不断出现。

为了将这些新的更改复制过来,我们启动了 DMS 持续复制(也称为更改数据捕获)任务。它会从源数据库事务日志中读取满载任务开始后创建的所有事务,并将其发送到目标数据库。这可确保我们的目标数据库与源数据库同步,最多会有少量滞后。

复制过程只用了几个小时就赶上了。此时,我们监控了 DMS 复制过程中的延迟,以确保它能够处理源数据库中发生的更改数量,并继续保持同步。

我们在后台运行了大约 10 天的 DMS 复制流程,在等待应用程序停止与源数据库会话并开始与目标数据库会话的同时,保持一切同步。我们已经提前向用户宣布了这一时间,因此已经为流量迁移设定了时间。

准备迁移流量

几个月前,我们计划了如何停止应用程序与源数据库会话,并让它们使用目标数据库:

  1. 停止从应用程序到源数据库的所有流量。此时,我们将进入 “通知 “不可用的停机期。
  2. 确保我们的复制已经跟上,以便源数据库的所有更新都能在目标数据库中得到反映。
  3. 允许我们的应用程序开始与目标数据库会话。这将结束我们的停机时间。

重要的是,不要让我们的一些应用程序在与源数据库会话的同时,其他应用程序也在与目标数据库会话。如果出现这种情况,目标数据库上的任何更改都不会反映到源数据库上,这意味着用户将获得不一致的数据。

我们为这一过程编写了 Python 脚本,使其清晰、易于重复,而且比手动操作要快得多。 完成得越快,通知用户的停机时间就越短。我们的目标是停机时间少于 5 分钟。最终,我们在之前的各种测试和实践中至少使用了 40 次该脚本。

我们选择在周六晚上进行迁移。这是因为这是我们最安静的时间之一,我们不必在半夜醒来,因为那时我们的警惕性会降低。

停止源数据库的流量

我们的脚本将通过在应用程序的所有连接上调用 `pg_terminate_backend` 来停止源数据库的所有流量。这只需要不到一秒钟的时间。我们还更改了应用程序使用的 PostgreSQL 用户密码,这意味着如果应用程序试图重新连接源数据库,就会出现身份验证错误。

检查复制是否跟上

DMS 在目标数据库中插入了一些有关复制状态的有用表格,这些表格每分钟更新一次。通过这些表格,我们可以了解目标数据库与源数据库之间的滞后情况。我们的迁移脚本会检查这些表,以确保目标数据库完全跟上。

为了更加安全,在应用程序停止与源数据库会话后,我们的迁移脚本会向源数据库写入一条记录,然后等待该记录安全到达目标数据库。这让我们更加确信,所有更改都已复制。

顺利切换流量

我们的应用程序要连接到数据库,需要知道数据库的位置以及相关 PostgreSQL 用户的用户名和密码。这些信息将通过以下格式的环境变量提供给我们的应用程序:

SQLALCHEMY_DATABASE_URI = postgresql://original-username:original-password@random-identifier.eu-west-1.rds.amazonaws.com:5432

如果我们希望应用程序连接到不同的数据库,就需要更新 URI 中的用户名、密码和位置,然后重新部署应用程序,使更改生效。重新部署应用程序大约需要 5 分钟。如果我们将重新部署应用程序作为迁移脚本的一部分,那么这将意味着额外 5 分钟的停机时间。为了尽量减少停机时间,我们在迁移前做了两项更改,这样就可以快速更改域名系统 (DNS) 而不是重新部署应用程序。

第一项更改是在源数据库和目标数据库上创建一个用户,用户名和密码相同。这意味着我们无需在迁移过程中更改提供给应用程序的用户名或密码。

第二项更改是在 AWS Route53 中为 “database.notifications.service.gov.uk “创建一个 DNS 记录,TTL(生存时间)为 1 秒。该记录有两个权重:

  1. 100% 的 DNS 结果加权到源数据库位置
  2. 0% 的 DNS 结果加权到目标数据库位置

我们将应用程序使用的 URI 设置为使用新用户名和密码,并将新域名用于数据库位置。

SQLALCHEMY_DATABASE_URI = postgresql://shared-username:shared-password@database.notifications.service.gov.uk:5432

现在,当我们要交换应用程序所指向的数据库时,迁移脚本只需更新 AWS 中的 DNS 权重,将结果 100% 发送到目标数据库位置,然后等待 1 秒 TTL 过期即可。然后,当我们的应用程序下一次尝试查询数据库时,它们将查询目标数据库。

当天发生的事情

当我们在 11 月 4 日星期六晚上集合时,我们已经建立了目标数据库,完整的加载过程已经运行,新的事务正在被复制过来。我们检查了一下,目标数据库和源数据库之间只有几秒钟的延迟。

然后,我们成功运行了迁移脚本,使应用程序停止与源数据库会话,开始与新的目标数据库会话。迁移过程中出现了短暂的停机时间,大约为 11 秒。这比我们的 5 分钟目标时间要短得多,因此我们非常高兴,我们的用户也非常高兴。

我们的收获

我们之所以选择使用 DMS,是因为它得到了 GOV.UK PaaS 的大力支持,而且我们还可以从 AWS 获得支持。如果将来要进行 PostgreSQL 到 PostgreSQL 数据库迁移,我们会投入更多时间尝试其他工具,如 pglogical。与其他工具相比,DMS 可能会增加更多的复杂性和不熟悉的复制过程。这也印证了 AWS 关于 PostgreSQL 到 PostgreSQL 迁移的说法。

GOV.UK Notify 迁移到 AWS 的下一步工作

现在我们已经迁移了数据库,下一步就是迁移应用程序。我们将把它们迁移到 AWS Elastic Container Service (ECS)。我们将在博客中介绍未来几个月的进展情况。

本文文字及图片出自 How we migrated our PostgreSQL database with 11 seconds downtime

余下全文(1/3)
分享这篇文章:

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注