在 JDBC 提交成功后处理 JMS 提交失败
Handle JMS commit failure after JDBC commit is success
在我的应用程序中,我从 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 事务处理(使用 2-phase commit protocol)。这在 Java EE 中非常常见,您有一个 MDB 使用消息然后使用数据库或另一个 JMS 提供程序。所有工作都是原子完成的,所以如果任何一个部分失败(例如 MDB 使用消息、数据库工作、将消息发送到另一个提供者)那么它们都会失败,以便跨系统的所有数据保持一致。
您似乎在避开 XA 事务(不确定为什么)并手动提交或回滚单个 JMS 和 JDBC 事务。这种方法总是存在(相当高的)数据不一致的风险。你如何处理它取决于你的具体限制。
明确地说,您引用的 ActiveMQ 文档中的伪代码不是使用两阶段提交。
在我的应用程序中,我从 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 事务处理(使用 2-phase commit protocol)。这在 Java EE 中非常常见,您有一个 MDB 使用消息然后使用数据库或另一个 JMS 提供程序。所有工作都是原子完成的,所以如果任何一个部分失败(例如 MDB 使用消息、数据库工作、将消息发送到另一个提供者)那么它们都会失败,以便跨系统的所有数据保持一致。
您似乎在避开 XA 事务(不确定为什么)并手动提交或回滚单个 JMS 和 JDBC 事务。这种方法总是存在(相当高的)数据不一致的风险。你如何处理它取决于你的具体限制。
明确地说,您引用的 ActiveMQ 文档中的伪代码不是使用两阶段提交。