Spring 为什么Amazon sqs不支持事务?
在Spring中,Rabbitmq支持事务。但是,AmazonSQS不支持Spring中的事务 对不起。我又添加了一些内容。 我在spring中测试了两个消息队列(rabbitmq、AmazonSQS),如下所示 我的目的是在用户无一例外地完成注册时,将用户电子邮件处理到队列以发送注册完成电子邮件Spring 为什么Amazon sqs不支持事务?,spring,amazon-web-services,rabbitmq,activemq,amazon-sqs,Spring,Amazon Web Services,Rabbitmq,Activemq,Amazon Sqs,在Spring中,Rabbitmq支持事务。但是,AmazonSQS不支持Spring中的事务 对不起。我又添加了一些内容。 我在spring中测试了两个消息队列(rabbitmq、AmazonSQS),如下所示 我的目的是在用户无一例外地完成注册时,将用户电子邮件处理到队列以发送注册完成电子邮件 //rabbit mq configuration.class @Bean public ConnectionFactory rabbitConnectionFactory() { Cachi
//rabbit mq configuration.class
@Bean
public ConnectionFactory rabbitConnectionFactory() {
CachingConnectionFactory connectionFactory =
new CachingConnectionFactory("localhost",5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
return connectionFactory;
}
@Bean
public SimpleMessageListenerContainer messageListenerContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(rabbitConnectionFactory());
container.setQueueNames(queue);
container.setMessageListener(exampleListener());
container.setTransactionManager(platformTransactionManager);
container.setChannelTransacted(true);
return container;
}
@Bean
public RabbitTemplate producerRabbitTemplate() {
RabbitTemplate rabbitTemplate = new RabbitTemplate(rabbitConnectionFactory());
rabbitTemplate.setQueue(queue);
rabbitTemplate.setMandatory(true);
rabbitTemplate.isChannelTransacted();
rabbitTemplate.setChannelTransacted(true);
return rabbitTemplate;
}
//UserService.class
@Autowired
private final UserRepository userRepository;
@Autowired
private final RabbitTemplate rabbitTemplate;
@Transactional
public User createUser(final User user){
rabbitTemplate.convertAndSend("spring-boot", user.getEmail()); // SignUp Completion email
final User user = userRepository.save(user);
if(true) throw new RuntimeException();
return user;
}
但是,上面的逻辑会发生runtimeException
如果发生异常,由于Spring中的事务性注释,Rabbit mq将不会向队列发送数据
//amazon sqs configuration.class
@Bean
public QueueMessagingTemplate queueMessagingTemplate(AmazonSQSAsync amazonSqs) {
//UserService.class
@Autowired
private final UserRepository userRepository;
@Autowired
private QueueMessagingTemplate messagingTemplate;
@Transactional
public User createUser(final User user){
messagingTemplate.convertAndSend("spring-boot", user.getEmail()); // SignUp Completion email
final User user = userRepository.save(user);
if(true) throw new RuntimeException();
return user;
}
但是,即使发生异常,sqs也将向队列发送数据
//amazon sqs configuration.class
@Bean
public QueueMessagingTemplate queueMessagingTemplate(AmazonSQSAsync amazonSqs) {
//UserService.class
@Autowired
private final UserRepository userRepository;
@Autowired
private QueueMessagingTemplate messagingTemplate;
@Transactional
public User createUser(final User user){
messagingTemplate.convertAndSend("spring-boot", user.getEmail()); // SignUp Completion email
final User user = userRepository.save(user);
if(true) throw new RuntimeException();
return user;
}
有人知道这是为什么吗?TLDR如何解决这个问题? 不要试图为此使用事务,想出一些方法使系统最终保持一致。
听起来您想执行“queue.sendmages”和“repository.save”,就好像它们是一个事务一样-要么都得到提交,要么都没有得到提交。问题是“事务”不是真正的事务性的,即使在兔子的例子中也是如此 考虑事务工作原理的基本知识:
开始
步骤,表示以下更改是事务的一部分commit
步骤以原子方式提交更改(使更改对读者可见)@Transactional
public User createUser(final User user){
messagingTemplate.convertAndSend("spring-boot", user.getEmail());
final User user = userRepository.save(user);
return user;
}
- 为此启动提交步骤时,它需要使消息(在队列中)和用户(在repo中)都可见
- 为了做到这一点,需要对队列和repo进行网络调用
- 这两个电话是问题的根源
- 如果一个成功,而另一个失败,那么您将处于不一致的状态
- 您可能会说“事务可以回滚”-但回滚将涉及另一个网络调用,这当然可能会失败
有很多方法可以使整个分布式系统具有事务性,但这是一个复杂的问题。考虑到暂时的不一致性,并建立机制使系统最终保持一致,通常会更容易、更快。SQS实际上只是一个消息队列。你能举例说明你想解决什么问题,以及你认为“交易”会有什么帮助吗?从那里我们可以帮助你解决这个问题。@Krease你能检查上面的内容吗?