【问题标题】:XA/JTA transaction: JMS message arrives before DB changes are visibleXA/JTA 事务:JMS 消息在 DB 更改可见之前到达
【发布时间】:2013-01-13 17:51:50
【问题描述】:

上下文是:

  • 生产者(JTA 事务 PT)正在向 JMS 队列发送消息并进行 DB 更新;
  • 消费者(JTA事务CT)监听同一个队列并在收到消息时读取DB;
  • 应用服务器 - WebLogic、DB - Oracle。

我观察到,有时 CT 不(还?)能够看到 PT 的数据库更改,如果已收到相应的 JMS 消息(PT 已提交?)。

JTA 似乎无法保证这种一致性(这在 Jurgen Holler 的演讲“性能的交易选择”中也得到了证实)。

避免此类问题的最佳方法是什么(除了明显的 - 不使用 JTA)?

谢谢。

【问题讨论】:

  • 只是另一个想法:由于 Weblogic 和 Oracle 已经被使用...您不妨添加 Coherence(数据库的分布式内存缓存)。您在更新数据库的同时更新缓存(直写式缓存),因此缓存具有可供消费者立即使用的最新值(或至少减少延迟)。
  • 我去看看,谢谢

标签: java jms jta distributed-transactions xa


【解决方案1】:

因此,似乎没有简单、优雅和防故障的解决方案。在我们的案例中,决定依赖简单的重新传递机制(抛出异常并让 JMS 消息在一定时间后重新传递)。

也考虑过:

  • 将 DB 数据源标记为并期望启动最后资源提交优化 (LRCO)(从而部分控制 XA 事务中的提交顺序)。由于依赖于应用程序服务器 (WL) 的内部而被拒绝。

  • 将 DeliveryDelay 设置为 JMS 消息,因此它只能在(假定)数据库同步结束的一段时间后使用。因缺乏保障而被拒绝,需要针对不同环境进行微调。

在其他答案中提到的Blog post 确实包含所有这些以及涵盖的其他几个选项(但没有确定的选项)。

【讨论】:

  • 我想最好的解决方案是同时启用重新交付机制和较小的交付延迟,以便仅在极端情况下才需要重新交付。
【解决方案2】:
【解决方案3】:

关于答案:

“所以似乎没有简单、优雅和防故障的解决方案 那。在我们的案例中,决定依靠简单的重新交付 机制(抛出异常并让 JMS 消息成为 一定时间后重新交付)。”

仅当您在 Transaction1 逻辑结束后开始的第二个事务能够检测到 Transaction 1 更改尚不可见并在技术异常时自行爆炸时,这才是失败证明。

如果您的事务 2 与事务 1 的进程不同,那么这很可能可以检查。很可能事务 1 的输出对于事务 2 的成功是必要的。有土豆只能做炸薯条……没有土豆可以炸了,下次再试。

但是,如果您的进程因数据库过时而中断,则该进程与在事务 1 本身上运行的进程完全相同。您只是将土豆添加到肠道(例如 db 表)中,并且未能检测到您的肠道溢出并继续运行事务以提高...这样的检查可能不在您的手中。

类似的事情,恰好是我的情况。

对此的理论解决方案很可能是通过创建一个与 JPA 的 @Version 字段等效的人工实体来尝试在 DB 上引发脏读,强制每个需要串行运行的进程在共同实体。如果事务 2 和事务 1 都更新了公共实体上的公共字段,则该进程将不得不中断 - 您在第二个事务上收到 JPA 乐观锁异常,或者如果您从数据库中收到脏读更新异常。

我还没有测试过这种方法,但很遗憾,这可能是需要的解决方法。

【讨论】:

  • 我已经测试了读写同一实体强制读写到达数据库的方法,并修复了问题。我们可以放心使用这种方法对业务逻辑进行逻辑序列化。
猜你喜欢
  • 1970-01-01
  • 2012-06-21
  • 2011-01-25
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-31
  • 2015-06-14
相关资源
最近更新 更多