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

英国政府通知 托管在 GOV.UK 平台即服务 (平台即服务)。 PaaS 即将退役,因此我们正在将所有基础设施迁移到我们自己的 Amazon Web Services (AWS) 帐户中。 这篇博文解释了我们如何迁移我们的 PostgreSQL 数据库停机时间最短。

该图显示了数据库迁移期间 11 秒内的错误峰值。

迁移我们的数据库

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

我们需要在自己的 AWS 账户中设置一个新数据库,并让所有应用程序与新数据库进行通信。 我们将这个新数据库称为“目标数据库”。

在我们自己的 AWS 账户中创建新的 PostgreSQL 数据库并不太困难。 困难的部分是传输我们的所有数据并让我们的应用程序使用这个新数据库,同时将停机时间降至最低。

关于我们的源数据库的更多信息

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

在通常的工作日,我们每秒执行大约 1,000 次插入或更新(有时低得多,有时高得多),再加上类似数量的读取。

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 复制过程中的延迟,以确保它能够处理源数据库发生的更改数量并继续保持同步。

我们在后台运行 DMS 复制过程大约 10 天,保持所有内容同步,同时等待应用程序停止与源数据库通信并开始与目标数据库通信。 我们已经提前向用户宣布了这个时间,所以已经设定了流量迁移的时间。

准备迁移流量

几个月前,我们计划如何停止我们的应用程序与源数据库通信并让它们使用我们的目标数据库。这是我们使用的过程:

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

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

我们为此过程编写了一个 Python 脚本,因此它可以是明确的、易于重复的,并且比手动完成要快得多。 完成得越快,Notify 用户的停机时间就越少。 我们的目标是停机时间少于 5 分钟。 在之前的各种测试和实践中,我们最终使用了该脚本至少 40 次。

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

停止流向我们的源数据库

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

检查复制是否已赶上

DMS 会根据复制状态将一些有用的表插入到我们的目标数据库中,这些表每分钟更新一次。 这些表使我们能够看到目标数据库和源数据库之间有多少滞后。 我们的迁移脚本将检查这些表,以确保我们的目标数据库完全跟上。

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

顺利交换流量

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

SQLALCHEMY_DATABASE_URI = postgresql://original-username:[email protected]:5432

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

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

第二个更改是在中创建 DNS 记录 AWS 路由53 对于“database.notifications.service.gov.uk”,TTL(生存时间)为 1 秒。 它有两条带有权重的记录:

  • 100% 的 DNS 结果已根据源数据库位置进行加权
  • 0% 的 DNS 结果被加权到目标数据库位置

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

SQLALCHEMY_DATABASE_URI = postgresql://shared-username:[email protected]:5432

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

当天发生了什么

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

然后,我们成功运行了迁移脚本,以便我们的应用程序将停止与源数据库通信并开始与新的目标数据库通信。 迁移期间有一段短暂的停机时间,大约 11 秒。 这比我们的 5 分钟目标要短得多,所以我们非常高兴,我们的用户也非常高兴。

我们学到了什么

我们选择使用 DMS 是因为它得到了 GOV.UK PaaS 的良好支持,而且我们还可以获得 AWS 的支持。 如果我们将来要进行 PostgreSQL 到 PostgreSQL 数据库的迁移,我们会投入更多时间尝试替代工具,例如 逻辑的。 与我们使用其他工具可能发现的情况相比,DMS 可能会增加更多的复杂性和不熟悉的复制过程。 这个备份 AWS 对 PostgreSQL 到 PostgreSQL 迁移的评价。

GOV.UK Notify 迁移到 AWS 的下一步是什么

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

Leave a Reply

Your email address will not be published. Required fields are marked *

近期新闻​

编辑精选​