2017-10-13 101 views
0

我想在这里理解一些东西。我的要求是我想将记录存储在数据库中,并希望将消息发送到队列,然后让它在相同的方法中说,如果它引发一些异常我不想发送消息,也不想提交数据库事务。 现在我想到使用春季交易,但由于两个不同的资源,想到使用JTA使用一些atomikos来同步资源 - 但我再次读到RMQ不支持2PC或XA等 无论如何,我继续前进,没有添加atomikos,我所做的一切都是确保我的频道和@Transaction注释保持关注,请参阅下面的示例代码 - 我没有在pom中添加任何特别的内容。交易处理Rabbit MQ和Spring AMQP

现在我的问题是如何工作,这与2PC有什么不同?以及哪些方法可能会出错,以及哪些情况会使用这种方法搞砸最终的一致性。令人惊讶的是,为什么我不必使用第三方jta。如果这一切都很好 - 当我们使用rmq和db使用spring的好东西时,这似乎是最终的一致性保证!对于微服务:)

如果这不是好的解决方案什么是替代方案 - 我想避免工作进程等,如果可能的话最终的一致性。

@Bean 
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) { 
    RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory); 
    rabbitTemplate.setChannelTransacted(true); 
    return rabbitTemplate; 
} 

@GetMapping 
@Transactional 
public void sampleEndpoint(@RequestParam boolean throwException){ 
    Customer a=new Customer(); 
    a.setCustomerName("XYZ"); 
    customerRepository.save(a); 
    rabbitTemplate.convertAndSend("txtest","Test"); 
    if(throwException) 
    throw new RuntimeException(); 
} 

我用的Postgres依赖于上面的例子中使用的弹簧引导1.5.7

回答

1

我建议你阅读Dave Syer's article: Distributed transactions in Spring, with and without XA

您需要在数据库事务之前启动Rabbit事务,以便rabbit事务与DB事务同步,并在DB tx之后立即提交,并在DB tx回退时回滚。

DB tx提交成功的可能性很小,但兔子tx回滚。这篇文章被称为“尽力而为1PC”。您需要处理重复邮件的小可能性。

你不显示所有的配置,但它看起来你的兔子tx将在数据库之前提交,这可能不是你想要的。

+0

我阅读文章,其内容翔实。谢谢。现在在这里没有太多的配置,但是正如你提到的那样,X事务从第一个开始 - 这里是如何工作的,在这种情况下,我只是简单地用@Transactional注释了其余的控制器。我想知道我是如何明确地开始使用兔子tx的。 – user3444718

+0

您需要使用文章中提到的'ChainedTransactionManager';结合'RabbitTransactionManager'和'DataSourceTransactionManager'。 –

+0

确保两件事 - 1)在我的例子中,你提到rabbit tx将在db之前首先提交 - 理由是因为 - 在这种情况下,db tx将首先启动(因为我们先有db操作),然后我们开始rabbit tx。现在提交按相反的顺序进行(如文章中所解释),正确的2)如果我使用了chainedtxmanager - 取决于我们在xml中定义的顺序,tx将首先提交 - 因此,如果我们先将xml中的rabbit tx mgr放入,然后dbtx mgr - rabbit tx将首先启动,然后是db - 因此db将首先提交,然后是rabbit tx。 – user3444718