首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Spring / RabbitMQ :事务管理

Spring / RabbitMQ :事务管理
EN

Stack Overflow用户
提问于 2013-07-02 16:53:15
回答 2查看 2.8K关注 0票数 10

为了简化我的问题,我

具有@Transactionnal方法的App1 createUser():

  • 在数据库中插入新用户
  • 在RabbitMQ中添加异步消息,以便用户接收通知邮件
  • (可能会增加一些代码,但不多)

App2与RabbitMQ消息使用者

  • 实时地使用邮件队列上的消息。
  • 读取数据库中的邮件数据
  • 寄出邮件

问题是,有时,App2试图在事务提交到App1之前使用RabbitMQ消息。这意味着App2无法读取数据库中的邮件数据,因为用户尚未创建。

一些解决方案可能是:

  • 在READ_UNCOMMITED上使用App2隔离级别
  • 在RabbitMQ消息传递中添加一些延迟(或在使用者上添加一些RetryTemplate )
  • 改变我们发邮件的方式..。

我见过春天有一个RabbitTransactionManager,但我不明白它应该如何工作。事务处理工具的内部元素似乎总是有点难以理解,而且文档也没有多大帮助。

有办法做这样的事吗?

  • 在@Transactionnal方法中向RabbitMQ队列添加消息
  • 当事务结束时,消息将提交到队列,而更改将提交给数据库。
  • 以便在DB事务结束之前不能使用该消息。

多么?例如,如果我发送同步RabbitMQ消息而不是异步消息,还会有什么期望呢?它会阻止线程等待响应什么的吗?因为我们确实为不同的使用程序发送同步和异步消息。

EN

回答 2

Stack Overflow用户

发布于 2016-02-05 16:30:30

我知道这已经很晚了,但我也遇到了同样的问题,因为当时我对“交易”的理解有限。所以这对其他人来说更重要的是,你碰巧发现了这个。

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

所以如果你有一种方法

代码语言:javascript
运行
复制
@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
}

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

可以在save()方法返回后嵌套@Transactional (它不是直接向前)将消息放到队列中。但是,您不能将消息放到队列中,并期望它不会被消耗。一旦它消失了。所以,如果需要的话,延迟把它放到队列中。

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

因此,我的建议是不要将这两个操作放在相同的@Transactional中

票数 3
EN

Stack Overflow用户

发布于 2013-07-03 10:31:49

我不太熟悉@Transactionnal和spring,但在AMQP中,标准消息队列不是事务性操作,因此您必须将数据存储在db (如果db连接是事务性提交事务)中,并且只在此之后才向代理发送消息。

正确的工作流看起来像App1: createUser -> notifyUser; App2: listenForNotifications

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17431367

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档