微服务分布式事务处理

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,182元/月
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
简介: 微服务分布式事务处理

当我们向微服务架构迁移时,如何处理好分布式事务是必须考虑的问题。这篇文章介绍了分布式事务处理的两种方案,可以结合实际采用合适的解决方案。原文:Handling Distributed Transactions in the Microservice world[1]


如今每个人(包括我)都在思考、构建微服务,分布式系统是微服务的核心原则和一切实现的上下文。


什么是分布式事务?


跨越网络上多个物理系统或计算机的事务被简单的称为分布式事务。在微服务世界中,事务被分割到多个服务中,需要按顺序调用这些服务以完成整个事务。


下面是一个单体电子商务系统使用事务的例子:

image.png

图 1: 单体中的事务


在上面的系统中,如果用户向平台发送 Checkout 请求,平台将创建一个本地数据库事务,该事务操作多个数据库表,以处理订单并从库存中保留商品。如果有任何步骤失败,事务(包括订单和保留的商品)可以回滚。这被称为 ACID(原子性 Atomicity、一致性 Consistency、隔离性 Isolation、持久性 Durability),由数据库系统保证。


下面是电子商务系统分解为微服务的情况:

image.png


图 2: 微服务中的事务


当我们解耦这个系统时,创建了微服务OrderMicroserviceInventoryMicroservice,各自有独立的数据库。当用户发起 Checkout 请求时,这两个微服务都将被调用从而将更改应用到各自的数据库中。因为事务是通过多个系统跨多个数据库的,所以现在这是一个分布式事务


微服务中的分布式事务有什么问题?


随着微服务体系架构的出现,事务可以跨越多个微服务,从而跨越数据库,因此我们现在无法利用数据库的 ACID 特性,从而面临以下关键问题:


如何保持事务的原子性?


原子性意味着事务要么完成所有步骤,要么没有完成任何步骤。在上面的例子中,如果InventoryMicroservice方法中的“保留商品”失败,如何回滚OrderMicroservice应用的“处理订单”?


如何处理并发请求?


如果某个微服务的对象被持久化到数据库中,同时有另一个请求读取相同的对象。服务应该返回旧数据还是新数据?在上面的例子中,一旦OrderMicroservice已经完成,那么InventoryMicroservice在执行更新的过程时,客户下单的请求中应该包括当前的订单吗?


如今,系统应该为失败而设计,其中主要的问题就是处理分布式事务。下面引用 Pat Helland 的话:


一般来说,应用程序开发人员不会简单的就能实现支持分布式事务的大型可伸缩应用系统。—— Pat Helland


可能的解决方案


在设计和构建基于微服务的应用时,上述两个问题非常关键。为了解决这些问题,下面列举几种方法:


  • 两阶段提交(Two-Phase Commit)
  • 最终一致性和补偿(Eventual Consistency and Compensation )/ SAGA
1. 两阶段提交


顾名思义,这种处理事务的方式有两个阶段,准备阶段和提交阶段,其中起到重要作用的是事务协调器(Transaction Coordinator),负责维护事务的生命周期。


工作方式:


在准备阶段,所有涉及到的微服务都准备提交,并通知协调器已经准备好完成事务。然后在提交阶段,事务协调器向所有微服务发出提交或回滚命令。


以电子商务系统为例:

image.png

图 3: 在微服务上成功的两阶段提交


在上面的示例中(图 3),当用户发送 Checkout 请求时,TransactionCoordinator将发起一个带有所有上下文信息的全局事务。首先,向OrderMicroservice发送 prepare 命令创建订单。然后,向InventoryMicroservice发送 prepare 命令保留商品。当两个服务都可以执行更改时,它们将锁定对象,不再接受其他更改,并通知TransactionCoordinator。一旦TransactionCoordinator确认所有微服务都已准备好应用更改,就会通过请求事务 commit 来要求这些微服务持久化所作的更改,然后所有对象才能被解锁。

image.png

图 4: 在微服务上失败的两阶段提交


在失败的场景中(图 4)——如果在任何时候有某个微服务没有做好准备,TransactionCoordinator将中止事务并发起回滚流程。图中由于某种原因,OrderMicroservice未能创建订单,但是InventoryMicroservice已经回复说它准备创建订单。TransactionCoordinator将请求InventoryMicroservice中止创建订单,并回滚所做的任何更改、解锁数据库对象。


优点


  • 该方法保证事务是原子的。交易结束时,要么所有微服务都成功,要么所有微服务都没有改变。
  • 其次,允许读写分离,在事务协调器提交更改之前,对象上的更改是不可见的。
  • 这种方法通过同步调用通知客户端成功或失败。


缺点


  • 没什么事情是完美的,两阶段提交与单个微服务的处理时间比起来慢很多,并且高度依赖于事务协调器,在高负载期间,事务协调器确实会降低系统的速度。
  • 另一个主要缺点是数据库行锁定,该锁可能成为性能瓶颈,并且可能出现两个事务相互锁定造成的死锁。
2. 最终一致性和补偿/SAGA


最终一致性的最佳定义之一是 microservices.io[2]描述的:每个服务在更新数据时发布一个事件。其他服务订阅事件,当接收到事件时,更新其数据。


在这种方法中,分布式事务由相关微服务上的异步本地事务来完成,微服务通过事件总线相互通信。


工作方式:


再以电子商务系统为例:

image.png

图 5: 最终的一致性/SAGA,成功的场景


在上面的例子中(图 5),客户端请求系统处理订单。在处理过程中,Choreographer发出一个 Create Order 事件,表示开始一个事务。OrderMicroservice监听到这个事件并创建一个订单,如果成功,发出一个 Order Created 事件。Choreographer侦听此事件,并通过发出 Reserve items 事件继续保留商品。InventoryMicroservice侦听此事件并保留商品,如果成功,发出 Items Reserved 事件。在这个例子中,这意味着事务的结束。


微服务之间所有基于事件的通信都是通过事件总线进行的,并由另一个系统编排以解决复杂性问题。


image.png

图 6: 最终的一致性/SAGA,失败场景


如果由于任何原因InventoryMicroservice未能保留商品(图 6),它会发出 Failed to Reserve Items 事件。Choreographer侦听此事件,并通过发出 Delete Order 事件启动补偿事务OrderMicroservice侦听此事件并删除所创建的订单。


优点


这种方法的一大优点是每个微服务只关注自己的原子事务。如果某个服务花费了更长的时间,其他微服务不会被阻塞,这也意味着不需要数据库锁。由于其基于异步事件的解决方案,这种方法可以使系统在高负载下具有高度的可伸缩性。


缺点


该方法的主要缺点是没有读取隔离。这意味着在上面的示例中,客户端可以看到已创建的订单,但在下一秒中,由于补偿事务,订单会被删除。此外,当微服务的数量增加时,调试和维护就变得更加困难。

结论


首先尽量避免分布式事务,如果正在构建新应用,那么就从单体开始,如 Martin Fowler 在 MonolithFirst[3]中所描述的那样:


更常见的方法是从单体开始,逐渐剥离边缘的微服务。这种方法可以在微服务体系架构的核心留下一个巨大的单体,大多数新的开发都发生在微服务中,而这个单体相对来说变化不大。— Martin Fowler


当一个事件需要在两个地方更新数据时,与两阶段提交相比,最终一致性/SAGA 方案是处理分布式事务的更好的方式,主要原因是两阶段提交在分布式环境中不能伸缩。不过最终一致性方案引入了新问题,例如如何以原子方式更新数据库和发出事件,因此采用这种方案需要开发和测试团队改变思维方式。


References:

[1] Handling Distributed Transactions in the Microservice world: https://medium.com/swlh/handling-transactions-in-the-microservice-world-c77b275813e0

[2] Event Driven Architecture: https://microservices.io/patterns/data/event-driven-architecture.html[3] MonolithFirst: https://martinfowler.com/bliki/MonolithFirst.html

目录
相关文章
|
16天前
|
存储 安全 Java
管理 Spring 微服务中的分布式会话
在微服务架构中,管理分布式会话是确保用户体验一致性和系统可扩展性的关键挑战。本文探讨了在 Spring 框架下实现分布式会话管理的多种方法,包括集中式会话存储和客户端会话存储(如 Cookie),并分析了它们的优缺点。同时,文章还涵盖了与分布式会话相关的安全考虑,如数据加密、令牌验证、安全 Cookie 政策以及服务间身份验证。此外,文中强调了分布式会话在提升系统可扩展性、增强可用性、实现数据一致性及优化资源利用方面的显著优势。通过合理选择会话管理策略,结合 Spring 提供的强大工具,开发人员可以在保证系统鲁棒性的同时,提供无缝的用户体验。
|
1月前
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
353 3
|
5月前
|
人工智能 安全 Java
智慧工地源码,Java语言开发,微服务架构,支持分布式和集群部署,多端覆盖
智慧工地是“互联网+建筑工地”的创新模式,基于物联网、移动互联网、BIM、大数据、人工智能等技术,实现对施工现场人员、设备、材料、安全等环节的智能化管理。其解决方案涵盖数据大屏、移动APP和PC管理端,采用高性能Java微服务架构,支持分布式与集群部署,结合Redis、消息队列等技术确保系统稳定高效。通过大数据驱动决策、物联网实时监测预警及AI智能视频监控,消除数据孤岛,提升项目可控性与安全性。智慧工地提供专家级远程管理服务,助力施工质量和安全管理升级,同时依托可扩展平台、多端应用和丰富设备接口,满足多样化需求,推动建筑行业数字化转型。
193 5
|
安全 应用服务中间件 API
微服务分布式系统架构之zookeeper与dubbo-2
微服务分布式系统架构之zookeeper与dubbo-2
|
负载均衡 Java 应用服务中间件
微服务分布式系统架构之zookeeper与dubbor-1
微服务分布式系统架构之zookeeper与dubbor-1
|
存储 消息中间件 Apache
比较微服务中的分布式事务模式
比较微服务中的分布式事务模式
190 2
|
8月前
|
Java 关系型数据库 数据库
微服务SpringCloud分布式事务之Seata
SpringCloud+SpringCloudAlibaba的Seata实现分布式事务,步骤超详细,附带视频教程
597 1
|
9月前
|
存储 运维 数据可视化
如何为微服务实现分布式日志记录
如何为微服务实现分布式日志记录
566 1
|
11月前
|
消息中间件 存储 负载均衡
微服务与分布式系统设计看这篇就够了!
【10月更文挑战第12天】 在现代软件架构中,微服务和分布式系统设计已经成为构建可扩展、灵活和可靠应用程序的主流方法。本文将深入探讨微服务架构的核心概念、设计原则和挑战,并提供一些关于如何在分布式系统中实现微服务的实用指导。
405 2
|
11月前
|
人工智能 文字识别 Java
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
尼恩,一位拥有20年架构经验的老架构师,通过其深厚的架构功力,成功指导了一位9年经验的网易工程师转型为大模型架构师,薪资逆涨50%,年薪近80W。尼恩的指导不仅帮助这位工程师在一年内成为大模型架构师,还让他管理起了10人团队,产品成功应用于多家大中型企业。尼恩因此决定编写《LLM大模型学习圣经》系列,帮助更多人掌握大模型架构,实现职业跃迁。该系列包括《从0到1吃透Transformer技术底座》、《从0到1精通RAG架构》等,旨在系统化、体系化地讲解大模型技术,助力读者实现“offer直提”。此外,尼恩还分享了多个技术圣经,如《NIO圣经》、《Docker圣经》等,帮助读者深入理解核心技术。
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?