mongock 能与 kubernetes 副本一起正常工作吗?

问题描述

Mongock 看起来很有前途。我们希望在具有多个并行运行的副本的 kubernetes 服务中使用它。

我们希望在部署我们的服务时,第一个副本将获得 mongockLock,并且它的所有 ChangeLog/ChangeSet 将在其他副本尝试运行它们之前完成。

我们有一个 mongodb 实例在我们的 kubernetes 环境中运行,我们希望 mongock ChangeLogs/ChangeSets 只执行一次。

mongockLock 会保证只有一个副本会运行 ChangeLogs/ChangeSets 以完成吗?

或者我是否需要启用事务(或其他一些配置)?

解决方法

我将先提供简短的答案,然后再提供长的答案。我建议你也阅读长篇,以便正确理解。

简答

默认情况下,Mongock 保证 ChangeLogs/changeSets 一次只能由一个 pod 运行。拥有锁的人。

长答案

幕后真正发生的事情(如果没有另外配置)是当一个 Pod 获取锁时,其他人也会尝试获取它,但他们不能,所以他们被迫等待一段时间(可配置,但默认为 4 分钟)与锁定配置的次数相同(默认为 3 次)。在此之后,如果我无法获取它并且仍有待应用的更改,Mongock 将抛出 MongockException,这意味着 JVM 启动失败(Spring 中默认发生的情况)。

这在 Kubernetes 中很好,因为它确保它会重新启动 pod。 所以现在,假设 Pod 再次启动并且已经应用​​了 changeLogs/changeSets,Pod 会成功启动,因为它们甚至不需要获取锁,因为没有待应用的更改。

没有事务支持的 MongoDB 和 Spring 等框架的潜在问题

现在,假设锁定和互斥是明确的,我想指出一个需要通过 changeLog/changeSet 设计来缓解的潜在问题。

如果您在 Kubernetes 等环境中存在 pod 初始化时间,则此问题适用,您的迁移需要比初始化时间更长的时间,并且在 pod 准备好/运行状况之前执行 Mongock 进程(这是它)。最后一个条件是非常需要的,因为它可以确保应用程序使用正确版本的数据运行。

在这种情况下,假设 Pod 启动 Mongock 进程。在 Kubernetes 初始化时间之后,该过程仍未完成,但 Kubernetes 突然停止了 JVM。这意味着一些更改集已成功执行,有些甚至没有启动(没问题,它们将在下一次尝试中处理),但是一个更改集被部分执行并标记为未完成。这是潜在的问题。下一次 Mongock 运行时,它会看到 changeSet 为挂起状态,并且会从头开始执行。如果你没有相应地设计你的 changeLogs/changeSets,你可能会遇到一些意想不到的结果,因为该 changeSet 覆盖的数据过程的某些部分已经发生并且它会再次发生。

这个,需要以某种方式减轻。要么借助事务等机制,要么借助将这一点考虑在内的 changeLog/changeSet 设计。

Mongock 目前提供“全有或全无”的交易,但它并没有多大帮助,因为它每次都会从头开始重试,最终可能会陷入无限循环。下一个版本 5 将提供每个 ChangeLogs 和 changeSets 的事务,加上良好的组织,是解决此问题的正确解决方案。

与此同时,此问题可以通过遵循 this design suggestions 来解决。

,

只是为了跟进... Mongock 的锁定机制适用于副本。为了解决“长时间运行的脚本”问题,我们将从 Kubernetes initContainer 运行我们的 Mongock 脚本。 K8s 将等待 initContainer 完成,然后再启动 pod 的主要服务容器。 对于交易,我们将遵循上述建议使我们的脚本具有幂等性。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...