分布式事务管理问题:如何处理跨多个服务的事务?
微服务是一个 分布式系统 。一个事务被分发给多个服务,这些服务被顺序或并行调用以完成整个事务。对于 微服务 架构 ,最常见的模式是每个微服务的数据库,因此事务也需要跨越不同的数据库。
随着微服务架构的出现,分布式事务管理存在两个关键问题:
子问题
如何解决这个问题?
在设计基于微服务的应用程序时解决这两个问题至关重要。以下是解决这些问题的两种方法:
两阶段提交 (2PC)
两阶段提交是数据库系统中众所周知的模式。这种模式也可以用于微服务来实现 分布式事务 。在两阶段提交中,有一个控制节点包含执行操作的大部分逻辑和参与节点(微服务)。它分两个阶段工作:
尽管 2PC 可以帮助在分布式系统中提供事务管理,但它也成为单点故障,因为事务的责任落在了协调者身上。随着阶段的数量,整体性能也会受到影响。由于协调器的健谈,整个系统受到最慢资源的约束,因为任何就绪节点都必须等待来自较慢节点的确认。此外,这种协调器的典型实现本质上是同步的,这可能导致未来吞吐量降低。2PC还是有以下缺点:
Saga
正如 Hector Garcia-Molina 和 Kenneth Salem 在其 1987 年计算机协会 文章 中所描述的那样,Saga是执行特定工作单元的一系列操作,并且通常相互交错。作为 Saga 一部分的每个操作都可以通过补偿操作回滚。Saga 保证所有操作成功完成,或者为所有执行的操作运行相应的补偿操作以回滚之前完成的任何工作。
补偿动作必须是幂等的,并且必须能够重试直到成功执行,本质上使它成为一个不会失败的动作,并且不需要人工干预来解决它的失败。Saga 执行协调器 (SEC) 为整个流程提供了保证和能力,使其成为成功或成功中止并具有必要回滚的事务。
Saga 模式在分布式事务场景中有何帮助?
微服务引入了另一组管理事务的问题,因为每个域驱动的服务都是单独部署并隔离运行的。使用微服务架构,单个业务流程将多个微服务组合在一起以提供整体解决方案。使用微服务架构实现 ACID(原子性、一致性、隔离性、持久性)事务非常困难,并且在某些情况下是不可能的。例如,在上述电子商务示例中,具有优惠券功能的微服务无法获取支付数据库的锁定,因为它在大多数情况下是外部服务。但是仍然需要某种形式的事务管理,所以这些事务被称为BASE事务:基本可用性、软状态和最终一致性。必须采取补偿措施来恢复作为交易的一部分发生的任何事情。
这是 Saga 模式完美契合的地方,因为它有助于:
实现 Saga 模式的不同方法
实现 Saga 模式有两种合乎逻辑的方式:编舞Choreography和编排orchestration。
编舞Choreography
在 Saga 编舞模式中,作为流程一部分的每个单独的微服务都会发布一个事件,该事件由后续的微服务接收。您必须在微服务开发生命周期的早期做出决定,以了解它是否会成为 Saga 模式的一部分,因为您必须选择一个合适的框架来帮助实现该模式。要采用特定的框架代码,必须使用注释、类初始化或其他配置更改来装饰微服务。在 Saga 编舞模式中,SEC 可以嵌入到微服务中,或者在大多数场景中是一个独立的组件
每当服务出现时,它都会向 SEC 注册,这使其成为可能跨越各种微服务的交易的一部分。SEC 在其日志中维护事件的顺序,这有助于它决定在发生故障时调用的补偿服务和顺序。
当参与分布式事务的微服务数量在 2 到 4 个之间时,首选编舞实现。在超过 4 个服务的情况下,应用编排实现更合适。
Saga 编舞模式是您开始微服务之旅(本质上是全新开发)并了解有必要适时引入流程微服务的理想选择。
编舞的缺点
编排orchestration
正如 Saga 编排模式的名称所暗示的那样,有一个编排器组件负责管理整个流程。如果进程在调用任何单个微服务时遇到错误,那么它也负责调用补偿服务。编排器帮助对 Saga 流进行建模,但也依赖底层框架按顺序调用服务,并在任何服务失败时进行补偿调用。
编排的优势
编排实现的唯一缺点是整个工作流程由 Saga Orchestrator 管理(单点风险)。
因此
由此产生的分布式事务问题得到了解决,但它的实现必须小心。