Saga分布式事务模式详解
Saga分布式事务模式详解
Saga分布式事务模式是一种用于维护分布式系统中数据一致性的设计模式。通过将事务分解为一系列本地事务,并在失败时执行补偿事务,Saga模式能够在微服务架构中实现跨服务的数据一致性。本文将详细介绍Saga模式的原理、实现方法及其适用场景。
Saga设计模式通过跨多个服务协调事务来帮助维护分布式系统中的数据一致性。Saga是一系列本地事务,其中每个服务执行其操作,并通过事件或消息启动下一步。如果序列中的步骤失败,则Saga执行补偿事务以撤消已完成的步骤。这种方法有助于维护数据一致性。
上下文和问题
事务表示可以包含多个操作的工作单元。在事务中,事件是指影响实体的状态更改。命令封装执行操作或触发后续事件所需的所有信息。
事务必须遵循原子性、一致性、隔离性和持久性(ACID)的原则。
- 原子性:所有作都成功或未成功。
- 一致性:数据从一个有效状态转换为另一个有效状态。
- 隔离:并发事务产生与顺序事务相同的结果。
- 持久性:即使发生故障,更改在提交后仍会保留。
在单个服务中,事务遵循ACID原则,因为它们在单个数据库中运行。但是,实现跨多个服务的ACID符合性可能更为复杂。
微服务体系结构中的挑战
微服务体系结构通常将专用数据库分配给每个微服务。此方法提供以下几个优势:
- 每个服务封装其自己的数据。
- 每个服务都可以根据其特定需求使用最合适的数据库技术和架构。
- 可以独立缩放每个服务的数据库。
- 一个服务中的故障与其他服务隔离。
尽管有这些优势,但此体系结构使跨服务数据一致性复杂化。传统的数据库保证(如ACID)不适用于多个独立托管数据存储。由于这些限制,依赖于进程间通信的体系结构或传统的事务模型(如两阶段提交协议)通常更适合Saga模式。
溶液
Saga模式通过将事务分解为一系列本地事务来管理事务。
每个本地事务:
- 在单个服务中以原子方式完成其工作。
- 更新服务的数据库。
- 通过事件或消息启动下一个事务。
如果本地事务失败,则Saga会执行一系列补偿事务,以扭转上述本地事务所做的更改。
Saga模式中的关键概念
- 补偿事务可以撤消或补偿其他具有相反效果的事务。如果传奇中的步骤失败,补偿事务将撤消可补偿事务所做的更改。
- 透视事务用作传奇中不返回的点。透视事务成功后,补偿事务不再相关。必须为系统完成所有后续作才能实现一致的最终状态。透视事务可以承担不同的角色,具体取决于传奇流程:
- 不可逆或不可编译的事务无法撤消或重试。
- 可逆和提交的之间的边界意味着透视事务可以是最后一个可撤消或可补偿的事务。或者,它可以是传奇中的第一个可重试作。
- 可重试事务遵循透视事务。可重试事务是幂等的,有助于确保传奇可以达到其最终状态,即使发生临时故障也是如此。他们帮助传奇最终实现了一致的状态。
Saga实现方法
这两种典型的传奇实现方法是编舞和业务流程。每个方法都有自己的一组挑战和技术来协调工作流。
编舞
在编舞方法中,服务交换事件时没有集中式控制器。通过编舞,每个本地事务都会发布触发其他服务中的本地事务的域事件。
编舞的好处 | 编舞的缺点 |
---|---|
适用于具有少量服务的简单工作流,不需要协调逻辑。 | 添加新步骤时,工作流可能会令人困惑。很难跟踪每个传奇参与者响应的命令。 |
协调不需要其他服务。 | 传奇参与者之间存在循环依赖关系的风险,因为它们必须相互使用命令。 |
不会引入单一故障点,因为责任分布在传奇参与者中。 | 集成测试很困难,因为所有服务都必须运行才能模拟事务。 |
配器
在业务流程中,集中式控制器或业务流程协调程序,处理所有事务,并告知参与者根据事件执行哪些作。业务流程协调程序执行传奇请求、存储和解释每个任务的状态,并使用补偿事务处理故障恢复。
业务流程的优点 | 业务流程的缺点 |
---|---|
更适合复杂的工作流,或者添加新服务时。 | 其他设计复杂性需要协调逻辑的实现。 |
避免循环依赖项,因为业务流程协调程序管理流。 | 引入故障点,因为业务流程协调程序管理完整的工作流。 |
明确职责分离简化了服务逻辑。 |
问题和注意事项
在决定如何实现此模式时,请考虑以下几点:
- 设计思维转变:采用Saga模式需要不同的思维模式。它要求你专注于跨多个微服务的事务协调和数据一致性。
- 调试传奇的复杂性:调试传奇可能比较复杂,特别是随着参与服务的数量的增长。
- 不可逆的本地数据库更改:无法回滚数据,因为传奇参与者将更改提交到各自的数据库。
- 处理暂时性故障和幂等性:当重复相同的作不会改变结果时,系统必须有效处理暂时性故障并确保幂等性。有关详细信息,请参阅幂等消息处理。
- 监视和跟踪传奇故事的需要:监视和跟踪传奇故事的工作流是维护作监督的重要任务。
- 补偿事务的限制:补偿事务可能并不总是成功,这可能会使系统处于不一致状态。
传奇中潜在的数据异常
数据异常是跨多个服务运行传奇时可能发生的不一致现象。由于每个服务都管理自己的数据,称为参与者数据,因此服务之间没有内置隔离。此设置可能会导致数据不一致或持续性问题,例如服务之间的部分应用更新或冲突。典型问题包括:
- 丢失的更新:当一个传奇修改数据而不考虑另一个传奇发生更改时,会导致覆盖或丢失更新。
- 脏读取:当传奇或事务读取另一个传奇已修改的数据时,但修改未完成。
- 模糊或不可恢复的读取:当传奇中的不同步骤读取不一致数据时,因为读取之间发生更新。
解决数据异常的策略
若要减少或防止这些异常,请考虑以下对策:
- 语义锁:当saga的可补偿事务使用信号灯指示更新正在进行时,使用应用程序级锁。
- 通勤更新:设计更新,以便可以按任意顺序应用更新,同时仍生成相同的结果。此方法有助于减少传奇之间的冲突。
- 悲观视图:重新排序传奇的序列,以便数据更新在可重试的事务中发生,以消除脏读读取。否则,一个传奇可以读取脏数据,或未提交的更改,而另一个传奇同时执行可补偿事务来回滚其更新。
- 重新读取值:确认数据在进行更新之前保持不变。如果数据发生更改,请停止当前步骤,并根据需要重启传奇。
- 版本文件:维护对记录执行的所有作的日志,并确保它们按正确的顺序执行,以防止冲突。
- 基于风险的值的并发:根据潜在业务风险动态选择适当的并发机制。例如,对低风险更新使用sagas,将分布式事务用于高风险更新。
何时使用此模式
在以下情况下使用此模式:
- 你需要确保分布式系统中的数据一致性,而无需紧密耦合。
- 如果需要回滚或补偿序列中的某个作失败。
此模式在以下情况下可能不适用:
- 事务紧密耦合。
- 补偿事务发生在早期参与者中。
- 存在循环依赖关系。
下一步
- 云原生数据模式
相关资源
实现此模式时,以下模式可能相关: