【问题标题】:What is the real delivered value of JTA?JTA的真正交付价值是什么?
【发布时间】:2014-06-28 01:27:22
【问题描述】:

我正试图围绕 Java Transactions API (JTA) 及其实现之一 Bitronix 下的 value。但是随着我对文档的深入挖掘,我不禁想到了以下简单的示例:

public interface Transactional {
    public void commit(Object);
    public void rollback();
}

public class TransactionalFileWriter extends FileWriter implements Transactional {
    @Override
    public void commit(Object obj) {
        String str = (String)obj;

        // Write the String to a file.
        write(str);
    }

    @Override
    public void rollback() {
        // Obtain a handler to the File we are writing to, and delete the file.
        // This returns the file system to the state it was in before we created a file and started writing to it.
        File f = getFile();

        // This is just pseudo-code for the sake of this example.
        File.delete(f);
    }
}

// Some method in a class somewhere...
public void doSomething(File someFile) {
    TransactionalFileWriter txFileWriter = getTxFW(someFile);
    try {
        txFileWriter.commit("Create the file and write this message to it.");
    } catch(Throwable t) {
        txFileWriter.rollback();
    }
}

不要太拘泥于上面的实际代码。这个想法很简单:一个事务文件编写器,它创建一个文件并写入它。 rollback() 方法删除文件,从而使文件系统恢复到 commit(Object) 之前的相同状态。

我在这里遗漏了什么吗?这就是 JTA 提供的全部内容吗?还是我上面的简单示例没有代表交易性的一组完全不同的维度/方面?我猜是后者,但尚未在 JTA 文档中看到任何具体内容。如果我遗漏了什么,那是什么,有人可以告诉我具体示例吗?我可以看到事务性是 JDBC 的一个重要组成部分,但希望获得一个 JTA 与数据库以外的东西一起使用的示例。

【问题讨论】:

  • 你有没有想过分布式事务&Transactional.getStatus()begin()setTransactionTimeout()。除了数据库,你有没有想过 JMS? JTA 提供的不仅仅是那个简单的界面。你也想过“当前活跃的交易”并加入吗?
  • 谢谢@AndreiI (+1) - 你能解释一下“当前活跃交易”是什么,“加入”它意味着什么?
  • 关于“当前活动事务”:有时您需要一种机制来决定是否要加入事务。在 JTA 中,您(据我所知)有一个附加到线程(可以暂停)的当前活动事务,并且在您的代码中,您可以动态决定您的 EntityManager(JPA 规范)加入它,以便提交您在其他一些请求中所做的更改。
  • 我想知道如果不是为了防止因赏金而关闭,这个问题需要多长时间才能关闭,因为过于宽泛或基于意见。
  • @OlegEstekhin 可能需要 7 天(如果有的话):) 因为赏金问题无法关闭。

标签: java jta bitronix


【解决方案1】:

正如其他人所提到的,JTA 的主要好处不是单个事务案例,而是多个事务的编排。

当在适当的上下文中使用时,您的“事务文件”是一个出色的概念性示例。

考虑一个人为的用例。

您正在上传一张包含相关元数据的图片,然后您想提醒基础设施该文件已到达。

这个“简单”的任务充满了可靠性问题。

例如,这个工作流程:

String pathName = saveUploadedFile(myFile);
saveMetaData(myFile.size(), myFile.type(), currentUser, pathName);
queueMessageToJMS(new FileArrivalEvent(user, pathName);

那段代码涉及文件系统和 2 个不同的服务器(DB 和 JMS)。

如果 saveUploadedFile 成功,但 saveMetaData 没有成功,那么您现在在文件系统上有一个孤立文件,可以说是“文件泄漏”。如果 saveMetaData 成功,但队列没有成功,则您已保存文件,但“没人知道”。交易的成功依赖于所有 3 个组件都成功执行其任务。

现在,输入 JTA(不是真正的代码):

beginWork();
try {
    String pathName = saveUploadedFile(myFile);
    saveMetaData(myFile.size(), myFile.type(), currentUser, pathName);
    queueMessageToJMS(new FileArrivalEvent(user, pathName);
} catch(Exception e) {
    rollbackWork();
} finally {
    commitWork();
}

现在它“一切正常”,或者“都不起作用”。

由于大多数系统没有事务管理器,因此通常人们会不厌其烦地让这种事情安全地工作。但是使用事务管理器(即 JTA),TM 会为您管理所有的事情,并且您可以保持代码干净。

如果您对行业进行调查,您会发现很少有交易经理。最初它们是“企业”级系统使用的专有程序。 TIBCO是有名的,IBM有,微软有。燕尾服曾经很流行。

但是对于 Java、JTA 和无处不在的 Java EE(等)服务器,“每个人”都有一个事务管理器。我们在 Java 世界中“免费”获得了这种编排。而且很方便。

Java EE 使事务管理器无处不在,事务处理成为了后台考虑因素。 Java EE 意味着“永远不必再次编写 commit()”。 (显然 Spring 提供了类似的设施)。

对于大多数系统,这不是必需的。这就是为什么大多数人对它知之甚少,或者根本不会错过它的原因。大多数系统填充单个数据库,或者根本不担心围绕多个系统编排的问题。这个过程可能是有损的,他们已经建立了自己的清理机制,无论如何。

但是当你需要它时,它非常好。同时提交多个系统可以解决很多问题。

【讨论】:

    【解决方案2】:

    JTA 的最大特点是您可以在一个应用程序中组合多个事务存储,并运行跨越这些独立存储的事务。

    例如,您可以拥有一个数据库、一个分布式事务键值存储和您的简单 FileWriter,并拥有一个对所有这些执行操作并一次提交所有存储中的所有更改的事务。

    看看infinispan。这是一个事务性数据网格,它使用 JTA,并且可以与其他 JTA 事务性服务结合使用。

    编辑:

    基本上,JTA 连接到X/Open XA 标准,它提供了直接在 Java 代码中与 X/Open XA 资源交互的方法。您可以使用现有的保存 X/Open XA 兼容资源的数据存储,例如数据库、分布式数据网格等。或者您可以通过实现javax.transaction.xa.XAResource 来定义自己的资源。然后,当您的User transaction 使用这些资源时,事务管理器将为您协调一切,无论资源位于何处,在哪个数据存储中。

    整个业务由负责同步独立数据存储的事务管理器管理。 JTA 没有附带事务管理器。 JTA 只是一个 API。如果您愿意,您可以自己编写 (javax.transaction.TransactionManager),但显然这是一项艰巨的任务。相反,您想要的是使用一些已经实现的具有事务管理器的 JTA 服务/库。例如,如果您在应用程序中使用 infinispan,您可以使用其事务管理器来允许您的事务也与不同的数据存储进行交互。最好向 JTA 接口的实现者寻求有关如何完成此操作的更多信息。

    您可以找到完整的 JTA API 文档here,虽然它很长。也有一些 tutorials 讨论如何使用 Java EE 事务管理器和更新多个数据存储,但它非常晦涩且不提供任何代码示例。

    您可以查看 Infinispan 的文档和教程,但我看不到任何将 Infinispan 与其他数据存储结合的示例。

    编辑 2:

    从评论中回答您的问题:您的理解或多或少是正确的,但我会尝试进一步澄清。

    用图片来解释架构和回答你的问题会更容易。以下内容来自 JTA 规范 1.1

    这是 X/Open XA 架构:

    每个数据存储(数据库、消息队列、SAP ERP 系统等)都有自己的资源管理器。在关系数据库的情况下,JDBC 驱动程序是一个资源适配器,它在 Java 中代表数据库的资源管理器。每个资源都必须通过 XAResource 接口可用(以便事务管理器即使不知道特定数据存储的实现细节也可以管理它们)。

    您的应用程序通过资源适配器与资源管理器(以访问特定资源)进行通信,并通过 UserTransaction 接口与事务管理器(以启动/完成事务)进行通信。每个资源管理器都需要首先初始化,并且必须针对全局事务进行配置(即跨越多个数据存储)。

    所以基本上,是的,数据存储是对一些资源进行分组的独立逻辑单元。它们还展示了允许执行本地事务的接口(仅限于该特定数据存储)。此接口可能性能更好,或者可能会公开一些特定于该数据存储的附加功能,而这些功能无法通过 JTA 接口使用。

    这是JTA环境的架构:

    小半圆代表JTA接口。在您的情况下,您最感兴趣的是 JTA UserTransaction 接口。您也可以使用 EJB(事务性 bean),应用服务器会为您管理事务,但这是另一种方式。

    从事务管理器的角度来看,实际执行 事务服务不需要暴露;只有高级接口需要 定义为允许事务划分、资源登记、同步和 恢复过程由事务服务的用户驱动。

    所以事务管理器可以理解为一个接口,它只代表用于管理事务的实际机制,例如 JTS 实现,但从整体上考虑也不是错误的。

    据我了解,如果您运行例如 JBoss 应用程序服务器,那么您已经配备了具有底层事务服务实现的事务管理器。

    【讨论】:

    • 感谢@ciamej (+1) - 关于您的分布式事务示例的一些跟进。 (1) 您能否解释一下“事务性商店”的含义,并提供一些示例? (2) 从您的示例来看,JTA 似乎用于协调对每个事务存储的提交?它是否处理编排(在正确的时间调用正确的事务存储等?以及(3)您能否提供一个代码示例(甚至是 GitHub 要点或演示这一点的代码链接),以提供 JTA 提交更改的示例同时有多家商店?再次感谢!
    • @IAmYourFaja 请看我的编辑。 (1) 事务存储是指任何符合 JTA 的数据库(带有实现 JTA 的 X/Open XA 接口部分的 JDBC 驱动程序)、数据网格、文件服务器等。 (2) 是的,它的职责是事务管理器 (3 ) 我还没有找到具体的代码示例。我想这是因为每个人都只想展示如何独立使用他们的产品,并且只是暗示可以将其与其他产品结合使用,尽管他们没有给出具体的代码示例。
    • Hibernate 还公开了一个 JTA 接口,因此您可以将其用作 JTA 事务中的数据存储。
    • 根据this:“一种选择是使用应用服务器的事务管理。每个JEE应用服务器都提供Java Transaction API (JTA),例如Orion、Jonas、Bea Weblogic、 Websphere,Jboss。”所以也许,例如,JBoss 有一些关于如何编排多个数据存储的教程。
    • @IAmYourFaja 请查看编辑。您的理解几乎是正确的,尽管我不会说数据存储需要事务性,而是他们提供它,并且可以组合。另外我认为事务管理器不必是单独的服务器。
    猜你喜欢
    • 1970-01-01
    • 2014-12-06
    • 1970-01-01
    • 2010-12-08
    • 2015-12-09
    • 2016-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多