java - JMS 消息排序和事务回滚

标签 java jms ibm-mq

我们正在构建一个系统,该系统将通过 JMS(如果重要的话使用 Websphere MQ)从一个应用程序向另一个应用程序发送消息。这些消息的形式为“Create x”或“Delete x”。 (这样做的最终结果是第三方系统需要被告知 Create 和 Delete 消息,因此 JMS 队列的 Read 端将与第三方系统对话,而 JMS 的 Write 端队列只是广播要处理的消息)

我们在这里担心的问题是其中一条消息是否失败。这里最初的想法是简单地将失败回滚到 JMS 队列中,让正常的重试机制处理它。这一直有效,直到您获得 Delete 后跟相同标识符的 Create,例如

  • 删除 123 - 失败,返回队列
  • 创造 123 - 成功
  • 删除 123 - 从较早的失败重试

这样做的最终结果是第三方被告知创建 123 然后立即删除 123,而不是相反。

虽然不理想,但从我一直在阅读的内容来看,消息亲和性似乎会在这方面有所帮助,这样我们就可以保证以正确的顺序处理消息。但是,我不确定当消息被处理并故障返回到队列时,消息亲和性将如何工作? (消息亲和性通常被认为是一个坏主意,但这里的负载不会很大,并且有毒消息的风险非常低。这只是我们正在与之交互的第三方有一个简短的风险我们关心的中断)

如果做不到这一点,是否有更好的想法来解决这个问题?

编辑 - 进一步的并发症。我们正在构建的与第三方集成的系统将取代他们直到最近才使用的来自不同供应商的系统。因此,有一堆数据已经在第三方中,但事实证明很难真正将其取出。 (第三方甚至不发回成功/失败消息,只是确认收到!),所以我们实际上不知道系统的初始状态。

最佳答案

解决此问题的 final方法是在消息中包含一个序列,这样较早的消息就不会覆盖较晚的消息。

曾几何时,您在银行的交易是按照到达顺序处理的。但是,正是这个确切的问题导致了这种情况的改变。人们开始意识到,根据交易处理的顺序,他们的账户余额可能会受到正面或负面影响。如果碰巧发生,它偶尔会成为人们的问题,但通常不会察觉到恶意。

后来,银行开始在白天对交易进行备忘,然后在处理之前将它们按照对银行最有利的顺序进行排序。例如,如果最大的支票先被清算,而账户中的钱用光了,那么几张较小的支票可能会退回,从而为银行产生多次退回费用。一旦发现这已成为普遍做法,它就会更改为始终以对账户持有人最有利的顺序应用交易。 (至少在美国是这样。)

这是一个常见问题,已经解决了很多次,第一次是在几十年前。企业级应用程序真的没有借口了

  1. 使用无法保证设计传递顺序的异步消息传递,以及
  2. 包含对交付顺序的内在依赖性,以确保交易和数据的完整性。

当作为传输问题处理时,消息亲和性的提及暗示了对此的解决方案。为保证消息顺序交付,需要满足以下条件:

  • 唯一的一个消息发送者
  • 发送消息的唯一一个节点。
  • 消息发送者和接收者之间只有一条路径。
  • 接收消息的唯一一个队列。
  • 在同步点下处理的所有消息。
  • 能够在存在孤立事务时暂停处理任何消息(连接异常处理)。
  • 输入队列上没有回退队列。
  • 如果消息通过 channel 则没有 DLQ。
  • 不对沿途的任何队列使用优先交付。
  • 唯一的一个消息接收者。
  • 只能通过向托管 QMgr 的节点添加 CPU 和内存来扩展应用程序。

或者可以在应用程序设计中使用备忘录发布、补偿事务或任何其他常用于消除序列依赖性的技术来解决该问题。

(旁注:如果所讨论的应用程序是现成的供应商软件包,在我看来这会产生可信度问题。如果出现像退出这样司空见惯的事情,那么任何应用程序都不能声称是健壮的消息可能会破坏数据完整性。)

关于java - JMS 消息排序和事务回滚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32352331/

相关文章:

java - PostgreSQL & JDBC 使用 `setArray` 设置整数数组抛出异常 "cannot cast type integer[] to integer"

java - 如何在 Java 中获得 UNIX 正常运行时间?

IBM MQ 绑定(bind)连接的 Java 程序中出现 java.lang.UnsatisfiedLinkError : mqjbnd05 (Not found in java. library.path) 错误

java - 将字符串从 EBCDIC 转换为 Unicode/UTF8

java - Spring MVC : Ensure parameter is valid, 通过多个 Controller 进行横切

java - 为什么会抛出此异常以及如何从中恢复?

java - 如何在 Java EE Web 应用程序 web.xml 中配置 JMS 监听器?

jms - Wildfly 10 Final 无限期地创建 ActiveMQ-client-global-threads

java - 如何在MQ消息中填写ApplIdentityData

java - JMS 无法连接到 websphere mq