【问题标题】:Camel: rollback jdbc transaction if consumer cannot acknowledgeCamel:如果消费者无法确认,则回滚 jdbc 事务
【发布时间】:2016-03-10 15:07:29
【问题描述】:

我有一个使用 AMQ/Camel 使用消息的后端应用程序。在每个消息处理期间,使用@Transactional JDBC DAO 完成数据库插入。我配置了两个消息代理。

问题:如果主代理停止,当前交换在消费者中变得陈旧:其中一些已经插入,但尚未向代理发送回 ACK。最后,broker 会进行消息回滚,然后应用程序再次获取相同的消息,从而导致数据库错误,因为它们已经被插入。

如何配置路由,以便在连接中断时尝试回滚?这只有在我以编程方式管理事务的情况下才有可能吗?

【问题讨论】:

    标签: spring jms apache-camel activemq


    【解决方案1】:

    首先,DAO 上的@Transactional 没有意义。您希望在完成请求后提交给数据库。对于网络应用程序,您通常在控制器上有事务边界。对于 JMS 消费者,您将它放在消费者(或附近)上。这样,您的事务边界就包含了您的业务逻辑以及持久化逻辑。一旦线程通过事务边界,该边界的事务管理器将提交(至少在它管理一个资源时,如数据库),并且在此之后无法回滚。

    也就是说,管理具有多个数据源的事务通常是一个难题。在大多数情况下,您会发现让系统对重复消息具有弹性比将提交同步到多个数据源更容易(例如,保留消息 ID 并在开始处理新消息之前查找它)。

    你有一些选择:

    1. 当我从 JMS 数据源消费并持久化到数据库时,我 通常将数据库的事务边界设置为最高 尽可能在路线上。您可以将.transacted() 设置为 第一条指令之一,或者更确切地说,您可以标记 JMS 消费者使用transacted=true,然后挂钩事务 提交到数据库的管理器。您可能仍会在提交到数据库时回滚代理,因此您需要一些逻辑来处理重复消息。
    2. 如果您真的想在提交到代理失败的情况下回滚提交到数据库,您唯一的选择是使用实现 XA 事务的事务管理器。这些事务管理器将实现两阶段提交(即 1. 询问所有资源是否准备好提交,2. 提交所有资源。如果第 1 阶段失败,则回滚所有事务。)如果您决定尝试这样做,您必须在骆驼端点标记您的事务边界,因为这是您想要提交到代理和数据库的时间。

    XA 事务将是一个比处理重复消息更复杂的解决方案,并且需要更多的开发人员。您已收到警告。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-09
      • 1970-01-01
      • 1970-01-01
      • 2014-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多