【问题标题】:How to design global distributed transaction(none database)? Can JTA use for none db transaction?如何设计全局分布式事务(无数据库)? JTA 可以用于无数据库事务吗?
【发布时间】:2012-04-05 10:39:21
【问题描述】:

我认为这是一个相当普遍的问题:如何将我的业务逻辑放在分布式系统环境中的全局事务中?举个例子,我有一个包含几个子任务的TaskA:

任务A {subtask1, subtask2, subtask3 ... }

这些子任务中的每一个都可以在本地机器或远程机器上执行,我希望TaskA通过事务以原子方式(成功或失败)执行。每个子任务都有一个回滚函数,一旦TaskA认为操作失败(因为其中一个子任务失败),它就会调用每个子任务的回滚函数。否则 TaskA 提交整个事务。

为此,我遵循“Audit trial”事务模式对每个子任务进行记录,因此TaskA可以知道子任务的操作结果,然后决定回滚或提交。这听起来很简单,但难点在于如何将每个子任务与全局事务关联起来?

当 TaskA 开始时,它会启动一个全局事务,其中子任务一无所知。为了让子任务知道它,我必须将事务上下文传递给子任务的每次调用。这实在是太可怕了!我的子任务要么在新线程中执行,要么通过 AMQP 代理发送消息在远程执行,很难巩固上下文传播的方式。

我做了一些研究,例如“事务模式 - 四种事务相关模式的集合”、“异步消息传递环境中的检查事务”,这些都没有解决我的问题。他们要么没有实际的例子,要么没有解决上下文传播问题。

我想知道人们如何解决这个问题?因为这种事务在企业软件中一定很常见。

X/Open XA 只是解决这个问题的方法吗? JTA 可以在这里提供帮助吗(我没有研究过 JTA,因为它与数据库事务有关,而且我正在使用 Spring,我不想在我的软件中涉及另一个 Java EE 应用程序服务器)。

有专家可以和我分享一些想法吗?谢谢。

结论

Arjan 和 Martin 给出了非常好的答案,谢谢。 最后我没有走这条路。经过更多研究,我选择了另一种模式“CheckPoint”1。

查看我的需求,我发现我的意图是“审核 Trial Transaction Pattern”是为了知道操作进行到了哪个级别,如果它失败了,我可以在重新加载一些上下文后在失败的地方重新启动它。其实这不是事务,失败后并没有回滚其他成功的步骤。这是 CheckPoint 模式的精髓。 然而,学习分布式事务的东西让我学到了很多有趣的东西。除了 Arjan 和 Martin 提到的。我还建议深入研究这个领域的人看看 CORBA,它是分布式系统的著名协议。

【问题讨论】:

  • 今天我读了JTA的东西,我认为这是要走的路,我需要实现我的XAResource以集成到全局事务中。这是一个有趣的话题,看起来以前没有多少人做过。我正在继续调查。
  • 事实上,由于 RMI/IIOP,Java 服务器之间的 EJB 调用“几乎”是 CORBA。有些供应商符合 CORBA,有些则不。

标签: java jta distributed-transactions


【解决方案1】:

您是对的,由于 JTA API 提供的 XA 事务管理器,您需要两阶段提交支持。

据我所知,Spring 本身并不提供事务管理器实现。 JtaTransactionManager 仅委托给通常由 JavaEE 实现提供的现有实现。

因此,您必须将 JTA 实现插入到 Spring 中才能有效地完成工作。以下是一些建议:

然后你将不得不实现你的资源管理器来支持两阶段提交。在 JavaEE 世界中,它包含在一个打包为 RAR 存档的资源适配器中。根据资源的类型,需要阅读/实现以下几个方面:

作为示例,我建议您查看经典“文件事务”问题的实现:

【讨论】:

    【解决方案2】:

    如果你想编写自己的事务资源,你确实需要实现一个 XAResource 并让它加入正在进行的事务,处理来自事务管理器的准备和提交请求等。

    数据源是最广为人知的事务性资源,但如前所述,它们并不是唯一的。您已经提到了 JMS 提供程序。各种缓存解决方案(例如 Infinispan)也是事务性资源。

    实施 XAResources 并使用 JTA API 的较低级别部分和更低级别的 JTS(Java 事务服务)并不是胆小的人的任务。 API 可能很陈旧,整个过程几乎没有文档记录。

    原因是创建自己的事务资源的常规企业应用程序极为罕见。事务性的全部意义在于对外部观察者执行原子操作。

    在绝大多数情况下可观察意味着操作的效果存在于数据库中。几乎每个数据源都已经是事务性的,因此该用例已被完全覆盖。

    另一个可观察到的影响是消息是否已发送,现有消息解决方案也完全涵盖了这一点。

    最后,更新内存映射中的(集群范围的)是另一个可观察到的效果,主要缓存提供者也涵盖了这一点。

    在使用外部企业信息系统 (EIS) 操作时,对交易效果的需求仍然存在,根据经验,此类系统的供应商会提供交易感知连接器。

    剩下的用例太少了,显然没有人真正费心写太多关于它的文章。有一些博客涵盖了一些基础知识,但很多内容将留给您自己的实验。

    如果您真的绝对需要走这条路,并且现有的交易资源之一无法满足您的需求,请尝试自己验证。

    【讨论】:

      【解决方案3】:

      您可以执行以下操作(类似于您的检查点策略):

      1. TaskA 在(本地)JTA 事务中执行,并尝试在委派给您的子任务之前保留必要的资源

      2. 子任务调用通过 JMS/XA 完成:如果第 1 步失败,则不会触发任何子任务,如果第 1 步提交,则每个子任务都会收到 JMS 调用

      3. 子任务(重新)尝试使用设置的 JMS 最大重新传递限制来处理其调用消息(有关如何执行此操作的信息,请参阅您的 JMS 供应商文档)

      4. 为 3 中的任何故障配置“死信队列”。

      这可行,假设:

      -在步骤 3 中重试是有意义的

      -死信队列中的消息需要一些人工干预

      如果这不可接受,那么还有 TCC:http://www.atomikos.com/Main/DownloadWhitepapers?article=TccForRestApi.pdf - 这可以看作是 REST 服务的“预留”模式。

      希望对你有帮助

      男人

      http://www.atomikos.com

      【讨论】:

        猜你喜欢
        • 2023-03-15
        • 1970-01-01
        • 2017-09-28
        • 2017-05-02
        • 2014-03-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多