我们有一个数据库密集型 Java 应用程序。我们使用的数据库是 SQL Server 2008。
我们正在考虑将 Java 应用程序转移到 2-3 节点负载平衡集群。我们经常添加应用程序功能/修复错误(因此会有新版本)。只要发布版本不涉及任何数据库更改,我们就可以一次从集群中取出一个节点进行维护并在其上部署较新的应用程序来更新 Java 应用程序。
但是,有时我们会发布涉及更新数据库的版本。(我们会运行脚本和存储过程来添加、删除或更新数据库上的数据。)这些操作有时需要大约一个小时。我们有没有办法处理这个问题,以便在更新数据库期间不必关闭应用程序?
在这种情况下,任何类型/配置的集群都能提供帮助吗?是否有任何可能的解决方案,即我们在 2 台服务器上拥有数据库(使用镜像或其他方式),我们将一台服务器脱机以进行更新过程,当更新结束时,我们将服务器重新联机,并使用自另一台服务器关闭以来发生的更改进行更新?
我对集群还不熟悉(尤其是 SQL 集群)。所以如果以上段落让您觉得有趣或不自在,请原谅我。
谢谢您的回答。
答案1
简而言之,您不能在两台服务器上运行 SQL Server 数据库,并在进行更新时将它们分裂。如果这样做,SQL Server 将无法让两个系统重新同步。一旦将它们拆分,您可能会在两边更改相同的行,或更改架构等,这将使一切无法重新组合在一起。
升级时,请考虑停机时间。在配置文件中放置一个标志,以便在数据库更改时快速轻松地将网站脱机。或者以更改不会使网站关闭的方式编写应用程序和更改,允许网站在进行更改时继续运行,然后将新网站置于更改之上。
如果操作正确,大多数数据库更改都可以在不关闭 UI 的情况下进行。
答案2
真正的问题是,在进行更新时,您是否需要能够从应用程序写入数据库?如果您可以处理只读,则可以获取数据库的快照,在快照上以只读模式运行应用程序,将更新应用于实际数据库,然后在所有操作完成后切换应用程序以使用实际数据库。
我认为“集群”存在一个根本问题,因为您谈论的并不是真正的集群,您谈论的其实是更类似于事务复制的东西(以便能够获得您谈论的“负载平衡”)。使用集群,您只有一个活动节点,除非您在单个集群上有多个 SQL 实例,但这需要重新编程您的应用程序来处理单独的实例,而且它不会真正实现您想要的效果。
TomTom 提到的原子性才是处理您所说的变更管理的真正问题。如果您在升级其他实例时将其中一个实例保持在可写模式,则当所有实例都升级时,实例之间的数据可能会不一致,因为您的脚本在发布新版本的过程中更改了代码。
答案3
您告诉我们。您能处理应用程序在一台服务器上更新数据库的同时另一台服务器上的数据库更新的情况吗?您会遇到一个严重的问题,那就是会丢失大量有保证的 SQL 行为(原子性)。这只能通过编程来解决,而不能通过自动化技术来解决。
因此,您不能询问集群是否好(提示:它不好)。如果您运行数据库的多个副本,并关闭其中一个,您如何处理临时更新并重新同步它们?