首页 > 解决方案 > 持续部署和数据库迁移

问题描述

这个问题就像“先是先有鸡还是先有蛋?”。

假设我们有一些源代码。使用 symfony 或 yii 编写。它有数据库迁移代码,可以处理一些数据库更改。

现在,我们有一些提交来更新我们的代码(例如新类)和一些数据库更改(更改旧列或添加新表)。

当我们在 localhost 开发或更新我们的开发服务器时,可以有时间停止服务\任何操作并更新服务器。但是当我们尝试在生产服务器上执行此操作时,我们会在一段时间内使所有内容崩溃,这不是一个选择。

为什么会发生这种情况——当我们拉取它(git\mercurial)时,我们的代码将被更新,但不会更新数据库,当代码将被执行时——它会抛出数据库异常。要修复它,我们应该运行内置框架迁移。所以最终我们的服务器将崩溃,直到调用迁移。

代码和迁移应该“一次”更新。

处理它的最佳做法是什么?

添加:像“运行拉取然后在一个调用中运行迁移”之类的解决方案 - 在高负载项目中不是一个选项。因为即使在第二次高负载时,也可能会出现一些条目\调用。

停止服务器我们也不能。

标签: symfonyyiicontinuous-integrationmigrationcontinuous-deployment

解决方案


实现零停机部署可能有点棘手,有很多方法可以实现这一目标。

至于数据库,建议以向后兼容的方式进行更改。因此,例如添加可为空的列或新表不会影响您现有的代码库,并且可以安全地完成。因此,如果您想添加一个新的不可为空的列,您可以分 3 步完成:

  1. 将新列添加为可为空
  2. 填充数据以确保没有空值
  3. 使列不为空

您至少需要为 1 和 3 重新部署。修改列时几乎相同,您创建一个新列,传输数据,释放使用新列的代码(可选地将旧列作为后备),然后删除旧列(加上后备代码)第三次部署。

这样可以确保您的数据库更改不会导致现有应用程序停机。这需要非常小心,显然需要您拥有一个允许快速发布的良好部署管道。如果需要几个小时才能发布此版本,则此方法将不好玩。

您可以复制数据库(甚至整个系统),进行迁移,然后切换到该实例,但在大多数应用程序中这是不可行的,因为在部署之间保持两个实例同步会很痛苦。我不建议在这方面投入太多时间,但我可能会对我的经验产生偏见。

在用较新的代码切换当前版本时,您有多种选择。像 kubernetes 这样花哨的基于云的解决方案使这种事情变得容易。您使用新版本创建第二个集群,然后将流量从旧集群缓慢路由到新集群。如果您只有一台服务器,将新版本部署到单独的文件夹是很常见的,执行所有管理任务,例如预热缓存,然后当版本准备好使用时,您将符号链接切换到最新版本。如果您真的希望它们是零停机时间,这两种方法都需要精心规划和调整。有各种各样的事情可能会导致问题,例如共享缓存被意外清除到会话未正确转移到新版本。无论什么时候'

以尽可能少的中断和故障进行部署的关键是对系统和应用程序进行良好的监控,以查看在部署过程中出现问题的地方,从而使其随着时间的推移更加稳定。


推荐阅读