如何管理多个实例之间共享的RDS数据库的数据库迁移?

Bas*_*ire 16 database-migration amazon-web-services amazon-ecs laravel aws-fargate

我知道一些潜在的解决方案,但它们都让我感觉很糟糕。

  1. 在管道(github操作)中,在fargate上运行一次性任务以在部署之前迁移数据库。
  2. 发布某种 cloudformation 事件作为部署挂钩并将其用作 lambda 触发器,然后 lambda 将执行迁移。
  3. 利用 laravel crons 和 onOneServer() 来持续检查是否需要迁移
  4. [问题,不好] docker 入口点命令在任务启动时运行数据库迁移。(不好,所有实例可能都会尝试快速连续迁移数据库)

每一个都有我不喜欢的东西。

  1. 这个将迁移数据库,然后部署。如果部署失败,数据库现在已迁移,为了修复它,我必须在失败后以某种方式在管道中运行数据库迁移回滚。而且,一般来说,依赖管道中的一次性任务感觉非常糟糕。
  2. 这个移动部件比我认为必要的要多。多点故障:cloudformation 事件、lambda 函数故障。此外,部署似乎是事件触发器,这意味着部署可能成功,但 lambda 数据库迁移失败,并且管道不知道。因此需要手动回滚部署。
  3. 这个感觉很老套,然而,似乎有最少数量的移动部件和最少的熵。然而,主要的缺点是,我认为这本质上需要 1/分钟的 cron 垃圾邮件php artisan migrate(没有任何可迁移的内容),以便它可以通过迁移捕获部署。好处是,使用 onOneServer(),它实际上应该解决这个问题:我们不希望多个实例都尝试在部署上迁移数据库,而只希望一个实例。这有一个很大的好处,就是将部署和迁移链接起来,所以如果部署失败,还没有迁移,如果迁移失败,至少可以更容易地将任务回滚到旧的任务版本。涉及的移动部件较少。每分钟发送垃圾邮件的资源开销php artisan migrate并且没有任何可回滚的内容,应该非常小/不明显的资源使用。但是,它在资源方面的效率低下仍然让我非常困扰。

还有其他解决方案吗?我预计有人可能会建议我使用环境变量控制实例,但我也不想这样做。如果我们部署并运行 3 个实例,它们都应该更新并且它们都是“相同”的实例状态。否则,我必须创建第二个服务,该服务也 24/7 运行以检查迁移作为其自己的特殊工作。我猜这是解决方案5:

  1. 与 24/7 运行的请求处理实例有一个单独的服务任务,其唯一的工作是运行 cron 并在部署后迁移数据库。但这也很糟糕,因为您有一个 24/7 运行的任务来检查部署,而部署并不那么频繁。

我认为解决方案 3 是我的首选解决方案,尽管它有资源开销。我很想听听其他人对这个问题的一些见解。我所处的情况是,如果我被公共汽车撞到,这条管道对于非操作人员来说确实应该很容易处理。在 Laravel 应用程序代码中保持简单似乎符合这一要求。我知道有计划任务/云信息事件解决方案,但请记住我有一个大目标as little entropy / moving parts as possible, within reason。

我已经阅读了关于这个主题的每一篇博客文章和每一篇谷歌点击,但还没有找到明确的答案。我自己提出了解决方案 3,但没有看到任何地方建议它。

在所有情况下都可能实现自动化数据库迁移太过雄心勃勃,应该开发并遵循手动流程。特别是如果数据库迁移包含不适用于旧实例的更改 - 在部署之前迁移它会暂时破坏这些更改。

Erm*_*ary 4

在部署之前运行数据库迁移(选项 1)是行业标准,也是您应该做的事情,无论您的云平台、数据库引擎或应用程序语言如何。

简而言之,长答案是数据库迁移是为了容错 - 如果出于某种原因您需要反转部署,您可以确切地知道发生了什么以便能够回滚。

大多数(如果不是全部)ORM(例如 .NET 的 Entity Framework 或 Java 的 Liquibase)允许您使用简单的命令回滚迁移。Laravel for PHP 附带的 Eloquent ORM 还允许您使用php artisan migrate:rollback.

部署之前管道中的一个步骤应该应用数据库迁移。如果部署因任何原因失败,您应该手动回滚。

这是应用程序和数据库在基础设施级别的交集 - 不幸的是,如果出现故障,预计需要一些手动工作。