【问题标题】:how to roll back a transaction happening between microservices?如何回滚微服务之间发生的事务?
【发布时间】:2015-12-08 09:14:52
【问题描述】:

我们有microservice 架构,其中大部分microservice 是独立的。但由于某些遗留原因,有一种情况是我们必须从另一个内部调用另一个 microservice

例如:下面的方法是Legal Service的一部分

@Autowired
public ServiceManager UserServiceManager;

public void updateUserLegalData(){

    //do db update of Legal info for the user

   userServiveManager.setAcceptedLegal(true);


}

上面有两个db transactions。一个是更新 legalService 数据库,另一个是更新 UserService 数据库。请注意 userService 是在单独的 VM 上运行的 microservice

我们看到合法服务数据库已更新但对 userService 的调用失败 (Internal server error) 的情况。所以这会使应用程序处于不一致的状态。我们如何以推荐的方式解决此问题?

谢谢

【问题讨论】:

  • 如果只有两个服务,那么一种方法是从第一个服务的事务方法调用第二个服务。首先更新本地数据库,然后调用第二个服务。如果第二次调用失败,则抛出异常。这也将导致第一个回滚。如果第二次成功,您很乐意使用 db 状态。

标签: java spring spring-mvc spring-data microservices


【解决方案1】:

这种情况只能通过 JTA 全局/分布式事务处理。 JTA 是 Java EE 标准的一部分,可以有各种实现者。 Atomikos 通常是首选工具。

Here is good writeup from Dave Syer (Spring ecosystem contributor). 它还包含工作示例。它有点过时了,但仍然相关。您可以在他的示例之上应用一些更现代的 Spring 抽象。

我为我的书创建了几个GitHub examples of JTA transactions。请注意,存在模拟错误,并且事务分布在 JMS 和 JDBC 数据源中。

但也请记住,由于涉及两阶段提交算法,跨各种数据源的 JTA 事务很慢。因此人们经常试图避免它们,而是以务实的方式处理不一致。

【讨论】:

  • apress.com/9781484207949。但它还没有完成。目前正在写最后一章。
  • >JTA transactions are slow and are nowadays often considered as architectural anti-pattern - 我认为反之亦然。如今,JTA 事务已优化到如此程度,以至于使用它们几乎没有任何开销。当您只使用单个事务资源或一个 tx 资源和非 tx 时,也可以应用一个 LRCO,从而减少与两阶段提交相关的任何可能成本。
【解决方案2】:

不要进行分布式事务。

为了与您现有的遗留系统集成,一种方法可能是一个单独的(微)服务,它侦听来自您的 userService 的更新事件并将相应的更新转发到 legalService。 Spring 集成可能适合这样的任务。

干杯, 迈克尔

【讨论】:

    【解决方案3】:

    好吧,如果您在互联网上阅读了一些有关该主题的信息,目前这是一个很大的崩溃点,但是每个人都同意一个答案,分布式事务不是解决问题的方法。它们太笨拙和错误,以至于我们不能依赖它们来保证数据的一致性。

    那么我们的选择是什么,人们正试图通过 Apache Kafka 或事件源(专注于保存更改数据的事件而不是保存数据本身)来协调微服务事务。那么这些有什么问题呢?好吧,它们与我们习惯的通常的编程模型完全不同,并且从技术和组织的角度来看非常复杂,因此您无需针对业务问题进行编程,而是针对技术挑战开始编程。

    那么有什么替代方案,我个人开发了另一个概念并写了一篇关于它的博客,它可能对你来说很有趣。在它的基础上,它在 J2EE 容器中使用了完整的微服务设计原则和 Spring Boot + Netflix,并且完全使用了事务,在这里写所有细节太长了,如果你有兴趣,可以从下面的链接中阅读。

    Micro Services and Transactions with Spring Boot + Netflix

    【讨论】:

      【解决方案4】:

      跨微服务的事务可能会变得复杂并且会降低系统速度,解决分布式事务问题的最佳方法之一是完全避免它们。 如果您避免跨微服务进行分布式事务,那么您将不会陷入这种情况。

      如果您必须跨微服务实现分布式事务,那么我认为有几种方法:

      两阶段提交协议 **最终一致性

      在您的情况下,我建议使用消息总线和标志在服务之间进行通信,因此,如果法律服务将数据添加到法律数据库中,则锁定该记录并在消息总线上发送消息,用户服务在它启动时将选择消息并在其末尾更新数据库并将 ack 消息发送到消息总线上,一旦收到 ack 消息就删除锁,否则在一定时间后删除/回滚记录。在您的情况下,这看起来很复杂但可靠且防故障的解决方案。

      【讨论】:

        猜你喜欢
        • 2020-10-29
        • 2020-01-30
        • 2018-02-21
        • 1970-01-01
        • 2017-02-14
        • 2021-12-13
        • 2010-09-30
        • 2021-06-20
        • 2020-02-10
        相关资源
        最近更新 更多