【问题标题】:Handle JMS commit failure after JDBC commit is successJDBC 提交成功后处理 JMS 提交失败
【发布时间】:2021-03-07 23:29:06
【问题描述】:

在我的应用程序中,我从 JMS 读取数据并写入数据库。为了处理这种情况the ActiveMQ documentation 有以下内容:

onMessage
try {
   if I have not processed this message successfully before {
   do some stuff in the database / with EJBs etc
   jdbc.commit() (unless auto-commit is enabled on the JDBC)
}
jms.commit()
} catch (Exception e) {
   jms.rollback()
}

我的问题是假设我们在执行jms.commit() 时遇到问题,然后我们回滚 jms 会话。但是我们的数据库提交已经完成。由于我们回滚了 jms 会话,队列将再次将该数据发送给消费者,这将导致数据库中的数据重复。我们在 ActiveMQ Artemis 队列上的故障转移场景中遇到过这种情况。有没有另一种方法可以处理这个问题而不会导致数据库重复或数据丢失?

【问题讨论】:

  • 您已经排除使用 XA 了吗?另外,当您说“两阶段提交”时,您指的是 XA 还是其他东西?如果您不使用 XA,那么您实际上并没有使用两阶段提交。请澄清。

标签: database transactions jms activemq-artemis


【解决方案1】:

这种情况通常会使用 XA 事务(使用2-phase commit protocol)来处理。这在 Java EE 中极为常见,其中您有一个 MDB 使用消息,然后使用数据库或另一个 JMS 提供程序。所有工作都是原子完成的,所以如果任何一个部分失败(例如 MDB 使用消息、数据库工作、向另一个提供者发送消息),那么它们都会失败,因此跨系统的所有数据都保持一致。

您似乎在避开 XA 事务(不知道为什么)并手动提交或回滚单个 JMS 和 JDBC 事务。这种方法总是存在(相当高的)数据不一致的风险。你如何处理它取决于你的具体限制。

需要明确的是,您引用的 ActiveMQ 文档中的伪代码不是使用两阶段提交。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-11
    • 2019-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-22
    • 1970-01-01
    • 2013-08-26
    相关资源
    最近更新 更多