如何在批处理中使用 AWS/RDS 切换数据库并避免停机?



对于我们的内部使用,我们在EC2实例上有一个Web应用程序,它从RDS/Postgres数据库中读取(不写入)数据。在一天中的部分时间里,会生成此数据库的新数据(运行 ~ 2 小时的批处理),并且数据直接写入同一数据库,当然会导致应用程序停机(~2 小时),直到数据完全写入。

在 AWS/EC2/RDS 上,管理这样的情况以不给应用程序带来停机时间,并且能够回滚到以前的版本,当然,如果在批处理过程中发生任何错误,当然也不会切换到新版本,这是什么好做法?

典型的 ETL(提取-转换-加载)过程通常通过以下方式工作:

  • 将数据加载临时表中
  • 运行脚本以将表的内容清理/转换为适合报告的格式
  • 发布表供用户使用

最后一步可以使用TRUNCATE然后SELECT INTO

如果停机时间太长,则另一种方法是让用户查询视图。然后,修改视图以指向第二组表(现在成为"主"表)。因此,每次加载时,视图都只是在表集之间交换。

我会考虑为此使用 RDS 快照。您将有一个可写的 RDS"主"实例(或黄金映像,如果您愿意),并且您将有一个刷新的只读 RDS 实例供您查询。

示例流程可能如下所示:

  • 确保您在托管区域中设置了别名别名记录(通过 Route 53)(在 VPC 中启用了 DNS 解析),以指向您当前的只读 RDS 实例(指向您在 RDS 控制台中看到的名称) - TTL 为 5-60 秒
  • 对主服务器执行 ETL/加载
  • 执行所需的任何验证活动
  • 为主 RDS 实例拍摄快照
  • 从主快照启动新的只读 RDS 实例
  • 将别名记录更改为指向新的只读 RDS 实例
  • 当所有应用程序数据库客户端都已故障转移(见下文)时,终止旧的只读 RDS 实例
  • (可选)停止主 RDS 实例以节省成本 - 直到下一次加载

为此,您需要对应用数据库连接池设置使用 CNAME,并确保连接定期老化 - 理想情况下,连接生存期不超过每隔几分钟,以最大程度地减少切换时间。还要注意某些应用运行时中的 DNS 缓存。从历史上看,例如,Java默认有一些相当长的缓存(你可以覆盖)。

您也可以自动执行此操作。一种选择是代码管道。

然后,您是否能够"回滚",具体取决于您保留快照的天数。要执行回滚,请从给定快照创建 RDS 实例并更改别名记录。

您的其他选项可能是使用 RDS 只读副本。但我不确定您是否可以在加载期间停止并(重新)启动PostgreSQL的复制过程 - 就像MySQL一样。而且我怀疑复制赶上可能会导致头部疼痛(也许某些 DDL 语句无法正常复制或按预期复制)。

相关内容

最新更新