【发布时间】:2016-10-18 02:40:10
【问题描述】:
我有一个多节点生产服务器(CentOS 7.x 上的 Tomcat 8.x;每个节点都是一个单独的 CentOS 实例),它使用一个 MySQL 数据库服务器(MySQL 5.7.x)。服务器的每个节点都将手动更新:系统管理员停止每个节点并部署新版本的应用程序(.war 文件)。这意味着服务不会停机,因为每时每刻都有至少一个工作节点。
数据库迁移是使用 Liquibase 变更集实现的,这些变更集位于 .war 文件中。因此,每个节点都会验证和更新(如果需要)数据库模式。实际上,只有第一个节点执行变更集,其他节点只是验证它。
问题是每个节点的更新之间存在时间间隔:当第一个节点已经用新的应用程序版本更新时,最后一个节点仍然在以前的应用程序版本上工作(可能使用数据库中的旧列例子)。可能会导致数据库不一致。
示例
假设服务器有 3 个节点。目前,他们正在开发版本 N 的应用程序。
下一个版本需要更改数据库架构:将列 title 重命名为 title_new。
为了能够在不停机的情况下更新数据库架构,我们需要使用“两步更改”:
- 版本 N+1:
- 新增一列
title_new, - 不再使用
title列(它被标记为已弃用); - 将
title列中的所有数据复制到title_new; - 使用列
title_new;
- 新增一列
- 版本 N+2 删除一列
title。
现在管理员要部署版本 N+1。他停止第一个节点进行更新,但其他两个节点仍在处理版本 N。当第一个节点更新时,一些用户可能会使用节点 2 或 3 更改他们的数据(有一个负载均衡器,将请求路由到不同的节点)。所以我们需要一种方法来禁止用户通过节点 2 和 3 进行任何更改,同时它们没有更新为 N+1 版本。
我看到了两种不同的方法来解决这个问题:
- 在应用程序级别使用一些
read_only模式 - 然后应用程序逻辑禁止用户进行任何更改。但是接下来我们需要实现一些方法来使用控制台或管理面板随时启用此模式(必须允许管理员启用此模式)。 - 在数据库级别使用
read_only模式。但我找不到任何可供 MySQL 执行此操作的现成方法。
问题:解决上述问题的最佳方法是什么?
附:应用基于 Spring 4.x 框架 + Hibernate 4.x。
【问题讨论】:
-
如果您选择选项 1,我会找到一种方法让部署负责在所有节点上触发只读模式,而不是让用户忘记关于它。
标签: java mysql database spring hibernate