Spring /RabbitMQ : transaction management

标签 spring transactions rabbitmq distributed-transactions

为了简化我的问题,我有
带有@Transactionnal 方法 createUser() 的 App1:

  • 在数据库中插入新用户
  • 在RabbitMQ中添加异步消息,让用户收到通知邮件
  • (可能有一些额外的代码,但不多)

  • 带有 RabbitMQ 消息消费者的 App2
  • 实时使用邮件队列中的消息
  • 读取数据库中的邮件数据
  • 发邮件

  • 问题是有时,App2 甚至在 App1 上提交事务之前尝试使用 RabbitMQ 消息。这意味着 App2 无法读取数据库中的邮件数据,因为用户尚未创建。
    一些解决方案可能是:
  • 在 App2 上使用 READ_UNCOMMITED 隔离级别
  • 在 RabbitMQ 消息传递中添加一些延迟(或消费者上的一些 RetryTemplate)
  • 改变我们发送电子邮件的方式...

  • 我已经看到 Spring 中有一个 RabbitTransactionManager,但我不明白它应该如何工作。事务处理内部的东西似乎总是有点难以理解,文档也没有多大帮助。

    有没有办法做这样的事情?
  • 在@Transactionnal 方法中向RabbitMQ 队列添加消息
  • 当事务结束时,将消息提交到队列中,并将更改提交到数据库
  • 使消息不能在DB事务结束前消费

  • 如何?例如,如果我发送同步 RabbitMQ 消息而不是异步消息,会发生什么?它会阻止线程等待响应还是什么?
    因为我们确实为不同的用例发送同步和异步消息。

    最佳答案

    我知道这已经晚了,但由于当时我对 @Transactional 的理解有限,我遇到了同样的问题。所以这对你偶然发现的其他人来说更是如此。

    当使用@Transactional 将数据保存到数据库时,在方法返回之前不会实际发生到数据库的保存,而不是在调用保存时。

    所以如果你有一个像

    @Transactional(readOnly=false)
    public void save(Object object) { //Object should be one of your entities
      entityManager.persist(object); //or however you have it set up
      rabbitTemplate.convertAndSend(message); //again - however yours is
    }
    

    即使您在将消息放入队列之前调用对象上的持久化,在方法返回之前持久化实际上不会发生,从而导致消息在方法返回之前和数据实际进入之前放入队列数据库。

    可以嵌套@Transactional 方法(虽然它不是直截了当的)可以将消息放在 save() 之后的队列中方法返回。但是,您不能将消息放入队列并期望它不会被使用。一旦它消失了。因此,如果需要,请延迟将其放入队列。

    如果您想以同步方式从队列接收响应。在我的函数示例中 - 您可以这样做,但是它只会使实际持久化数据花费更长的时间,因为它将在方法返回并实际持久化数据之前等待工作人员的响应。 (还请记住,从排队消息接收响应有一个超时)。

    所以我的建议是不要将这 2 个操作放在同一个 @Transactional 中

    关于 Spring /RabbitMQ : transaction management,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17431367/

    相关文章:

    c# - 使用 finally 而不是 catch

    mysql - MySQL是如何实现事务的

    java - Spring AMQP - 将消息返回到队列的开头

    java - Spring - 等待rabbitmq消息监听器完成

    java - AutowireCapableBeanFactory.autowireBeanProperties() 似乎不适用于 xml 配置的上下文

    java - Spring AOP 关于注解 Controller 的建议

    c# - 跨系统交易

    php - NodeJS AMQP 客户端无法连接

    java - Spring Web Security 中的自定义方法

    java - Spring Jms 每秒发出警告消息