Camel:如果消费者无法确认,则回滚jdbc事务

时间:2016-03-10 15:07:30

标签: spring jms apache-camel activemq

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

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

如何配置路由以便在连接断开时尝试回滚?这只有在我以编程方式管理交易时才有可能吗?

1 个答案:

答案 0 :(得分:1)

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

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

你有一些选择:

  1. 当我从JMS数据源使用并持久存储到数据库时,我 通常将数据库的事务边界设置为高 在路线尽可能。您可以.transacted()为 第一条指令之一,或者您可以标记JMS 使用transacted=true的消费者,然后挂钩事务 提交到数据库的管理器。您可能仍然在提交数据库时回滚代理,因此您需要一些逻辑来处理重复的消息。
  2. 如果您确实要在对代理的提交失败时将提交回滚到数据库,那么您唯一的选择是使用实现XA事务的事务管理器。这些事务管理器将实现两阶段提交(即1.询问所有资源,如果它们已准备好提交,2。提交所有资源。如果阶段1失败,则回滚所有事务。)如果您决定尝试此操作,您必须在camel端点标记事务边界,因为这是您要提交到代理和数据库的时间。
  3. XA事务将是一个比处理重复消息更复杂的解决方案,它将需要更多的开发人员。你被警告了。