简体   繁体   English

如何回滚微服务之间发生的事务?

[英]how to roll back a transaction happening between microservices?

we have microservice architecture where for most part each microservice is independent. 我们有microservice架构,大多数情况下每个microservice都是独立的。 But for some legacy reasons, there is a situation where we have to call another microservice from within another. 但由于某些遗留原因,我们不得不从另一个内部调用另一个microservice

eg: the following method is part of Legal Service 例如:以下方法是Legal Service一部分

@Autowired
public ServiceManager UserServiceManager;

public void updateUserLegalData(){

    //do db update of Legal info for the user

   userServiveManager.setAcceptedLegal(true);


}

There are two db transactions going on above. 上面有两个db transactions one is updating legalService db and other is updating UserService db. 一个是更新legalService db,另一个是更新UserService db。 please NOTE userService is a microservice running on a separate VM. 请注意userService是在单独的VM上运行的microservice

we are seeing situations where legal Service db is updated but call to userService is failing ( Internal server error ). 我们看到合法服务数据库更新但调用userService失败的情况( Internal server error )。 so this leaves the application in an inconsistent state. 所以这使应用程序处于不一致状态。 How can we fix this in a recommended way? 我们如何以推荐的方式解决这个问题?

Thanks 谢谢

This situation can be handled only with JTA global/distributed transactions. 只能使用JTA全局/分布式事务处理此情况。 JTA is part of Java EE standard and can have various implementors. JTA是Java EE标准的一部分,可以有各种实现者。 Atomikos is often tool of choice. Atomikos通常是首选工具。

Here is good writeup from Dave Syer (Spring ecosystem contributor). 这是Dave Syer(Spring生态系统贡献者)的精彩文章。 It contain also working examples. 它还包含工作示例。 It's little bit outdated, but still relevant. 它有点过时,但仍然相关。 You can apply some more modern Spring abstractions on top of his examples. 您可以在他的示例之上应用一些更现代的Spring抽象。

I created few GitHub examples of JTA transactions for my book. 我为我的书创建了几个GITHub的JTA事务示例 Notice that there are errors simulated and transaction is spread across JMS and JDBC datasources. 请注意,模拟了错误,并且事务分布在JMS和JDBC数据源中。

But also bear in mind that JTA transactions across various data sources are slow, because of 2-phased commit algorithm involved. 但同时请记住,由于涉及两阶段提交算法,跨各种数据源的JTA事务处理速度很慢。 So often people try to avoid them and rather deal with inconsistencies somehow pragmatically. 因此,人们常常试图避免它们,而是以务实的方式处理不一致问题。

Don't do distributed transactions. 不要做分布式交易。

For integration with your existing legacy system one approach could be a separate (micro)service which listens to update events from your userService and forwards the respective updates to the legalService. 为了与现有遗留系统集成,一种方法可以是单独的(微)服务,它监听来自userService的更新事件,并将相应的更新转发给legalService。 Spring integration may be suitable for such a task. Spring集成可能适合于这样的任务。

Cheers, Michael 干杯,迈克尔

Well if you read little bit about the subject in the internet, it is a big debacle point at the moment but there is one answer that everybody agrees on it, distributed transactions are not way to go for it. 好吧,如果你在互联网上读到一些关于这个主题的内容,那么目前这是一个很大的崩溃点,但有一个答案是每个人都同意它,分布式交易是不可取的。 They are too clumsy and buggy that we can't rely on them for data consistency. 它们太笨拙和错误,我们不能依赖它们来保证数据的一致性。

So what is our options then, people are the moment trying to coordinate micro service transactions via Apache Kafka or with Event Source (which concentrate on saving events which are changing the data instead of saving the data itself). 那么我们的选择是什么呢,人们正在尝试通过Apache Kafka或事件源协调微服务事务(专注于保存更改数据而不是保存数据本身的事件)。 So what is the problem with those? 那么问题是什么? Well they are quite different then usual programming model that we get used to and at technical and organisational point of view quite complex, so instead of programming for Business Problems, you start programming against the technical challenge. 它们与我们习惯的通常编程模型完全不同,并且在技术和组织的角度来看相当复杂,因此不是针对业务问题编程,而是开始针对技术挑战进行编程。

So what is the alternative, I personally developed an another concept and wrote a blog about it, it might be interesting for you. 那么替代方案是什么,我个人开发了另一个概念并写了一篇关于它的博客,它可能对你有意思。 In its basics, it uses full micro service design principles and Spring Boot + Netflix in a J2EE container and fully using the transactions, it is too long to write all details here, if you are interested you can read the from the link below. 在它的基础知识中,它使用完整的微服务设计原则和Spring容器中的Spring Boot + Netflix并完全使用这些事务,这里写的所有细节都太长了,如果您有兴趣可以从下面的链接中阅读。

Micro Services and Transactions with Spring Boot + Netflix Spring Boot + Netflix的微服务和事务

Transaction across microservices can become complex and can slow down the system, one of the best ways to solve the problem of distributed transactions is to avoid them completely. 跨微服务的事务可能变得复杂并且可能使系统变慢,解决分布式事务问题的最佳方法之一就是完全避免它们。 If you avoid distributed transactions across microservices then you will not end up in such situation. 如果您避免跨微服务的分布式事务,那么您将不会遇到这种情况。

If at all you have to implement distributed transactions across microservices then I think there are a couple of ways : 如果你必须在微服务中实现分布式事务,那么我认为有两种方法:

Two-phase commit protocol **Eventual Consistency 两阶段提交协议**最终一致性

In your case, I would recommend using message bus and flag to communicate among services , So if legal service adds the data into legal database put a lock on that record and send message on message bus , user service when it is up it will pick the message and update database at its end and send ack message onto the message bus, once ack message is received remove the lock otherwise delete/rollback the record after certain time duration. 在你的情况下,我建议使用消息总线和标志在服务之间进行通信,因此,如果合法服务将数据添加到合法数据库中,则锁定该记录并在消息总线上发送消息,用户服务在启动时将选择消息并在其末尾更新数据库并将ack消息发送到消息总线上,一旦收到ack消息,则删除锁定,否则在一定时间后删除/回滚记录。 This looks complex but reliable and failure-proof solution in your case. 在您的情况下,这看起来很复杂但可靠且防故障。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM