如何设计全局分布式事务(无数据库)? JTA可以用于无数据库事务吗?

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

TaskA {subtask1,subtask2,subtask3 …}

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

为此,我按照“审计试用”事务模式来记录每个子任务,因此TaskA可以知道子任务的操作结果,然后决定回滚或提交。 这听起来很简单,但是,困难的部分是如何将每个子任务与全局事务相关联?

当TaskA开始时,它会启动一个关于哪个子任务什么都不知道的全局事务。 为了使子任务意识到它,我必须将事务上下文传递给每个子任务调用。 这真是太可怕了! 我的子任务可以在新线程中执行,也可以通过AMQP代理发送消息在远程执行,很难巩固上下文传播的方式。

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

我想知道人们如何解决这个问题 因为这种交易必须在企业软件中很常见。

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

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

结论

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

根据我的要求,我发现我的“审核试验事务模式”的意图是知道操作已经进行到哪个级别,如果它失败了,我可以在重新加载某些上下文后在失败的地点重新启动它。 实际上这不是事务,它在失败后没有回滚其他成功的步骤。 这是CheckPoint模式的本质。 然而,研究分布式交易的东西让我学到了很多有趣的东西。 除了Arjan和Martin提到的。 我还建议人们深入研究这个领域,看看CORBA,这是一个众所周知的分布式系统协议。

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

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

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

  • JOTM
  • JBossTS基于Arjuna。
  • Atokimos

然后,您必须实现资源管理器以支持两阶段提交。 在JavaEE世界中,它包含一个打包为RAR存档的资源适配器。 根据资源类型,以下方面是读取/实现:

  • XAResource接口
  • JCA Java Connector Architecture主要涉及远程连接
  • 如果需要节点之间的事务传播,则为JTS Transaction Service

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

  • 来自JBoss Transactions的事务文件管理器
  • XADisk项目

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

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

实现XAResources并使用JTA API的低级部分和更低级别的JTS(Java事务服务)对于胆小的人来说不是一项任务。 API可能过时,整个过程几乎没有记录。

原因是创建自己的事务资源的常规企业应用程序极为罕见。 事务性的整个要点是为外部观察者做一个primefaces的动作。

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

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

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

在使用外部企业信息系统(EIS)进行操作时,对事务影响的需求仍然存在,并且根据经验,此类系统的供应商提供事务感知连接器。

剩下的用例的颤抖是如此之小,以至于显然没有人真正打扰过多写它。 有一些博客涉及一些基础知识,但很多将留给你自己的实验。

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

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

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

  2. 子任务调用是通过JMS / XA完成的:如果步骤1失败,则不会触发任何子任务,如果步骤1提交,则将在每个子任务中接收JMS调用

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

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

这有效,假设:

– 步骤3中的重试是有道理的

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

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

希望这可以帮助

家伙

http://www.atomikos.com