事务补偿模式

如果一起定义最终一致的操作的一系列步骤,在执行过程中有一个或多个步骤失败,则撤销该操作。通常,托管在云上的实现复杂业务流程和工作流程的应用程序会存在遵循最终一致性模型的操作。

背景和问题

在云中运行的应用程序会频繁修改数据。该数据可能会分布在不同地理位置的不同数据源上。为了提高性能和避免分布式环境中的竞争,应用程序不应该提供强事务一致性。相反,应该实现最终的一致性。在这个模型中,典型的业务操作包括一系列单独的步骤。当执行这些步骤时,系统状态的总体视图可能不一致,但是当操作已经完成并且所有步骤都已执行时,系统应该再次变得一致。

数据一致性入门解释了分布式事务为何不能很好地扩展的原因,以及最终一致性模型的原理。 最终一致性模型中的挑战是如何处理失败的步骤。在这种情况下,可能需要撤消操作中以前步骤完成的所有工作。但是,数据不能简单地回滚,因为应用程序的其它并发实例可能会更改它。即使在数据未被并发实例更改的情况下,撤消步骤可能不仅仅是恢复原始状态的问题。可能需要应用各种特定于业务的规则(请参阅案例部分中介绍的旅游网站)。 如果实现最终一致性的操作涉及多个异构数据存储,则撤消操作中的步骤将依次访问每个数据存储。必须可靠地撤消在每个数据存储中执行的工作,以防止系统保持不一致。 并不是所有受实施最终一致性的操作影响的数据都可能保存在数据库中。在面向服务的架构(SOA)环境中,操作可以调用服务中的动作,并引起该服务所持有的状态发生更改。要撤消操作,此状态更改也必须撤消。这可能涉及再次调用该服务并执行另一个反转第一个操作的动作。

解决方案

解决方案是实施事务补偿。补偿事务中的步骤必须撤销原始操作中的步骤的影响。补偿事务可能无法简单地将当前状态替换为系统在操作开始时所处于的状态,因为该方法可能会覆盖应用程序的其它并发实例所做的更改。相反,它必须是一个智能的进程,考虑到并发实例完成的任何工作。该过程通常由具体应用程序,由原始操作执行的工作性质驱动。 一个常见的方法是使用工作流来实现最终一致的、需要补偿的操作。随着原始操作的进行,系统记录关于每个步骤的信息以及该步骤执行的工作如何撤销。如果操作在任何时候都失败,则工作流通过完成的步骤回滚,并反转每个步骤的工作。请注意,补偿事务可能不必以原始操作的完全相反的顺序撤销工作,并且可以并行执行一些撤销步骤。

这种方法类似于Clemens Vasters博客中讨论的Sagas策略。 事务补偿是最终一致的操作,也可能失败。系统应该具备在故障点恢复事务补偿,并继续执行的能力。可能需要重复失败的步骤,因此补偿事务中的步骤应定义为幂等命令。更多信息请参阅Jonathan Oliver博客上的幂等模式。 在某些情况下,可能只能通过手动干预才能从失败的步骤中恢复。在这些情况下,系统应该发出警报,并提供尽可能多的关于故障原因的信息。

问题和注意事项

在决定如何实现此模式时,请考虑以下几点: 确定执行最终一致性的操作中的步骤何时失败可能并不容易。步骤可能不会立即失败,但是可以阻止。可能需要实施某种形式的超时机制。 补偿逻辑不容易泛化。事务补偿是特定于应用程序的。它依赖于拥有足够信息的应用程序能够在故障操作中撤消每个步骤的影响。 应该将补偿事务中的步骤定义为幂等命令。如果补偿事务本身失败,则可以重复这些步骤。 处理原始操作步骤的基础设施和事务补偿必须具有弹性。不能丢失补偿失败步骤所需的信息,并且必须能可靠地监视补偿逻辑的进度。 事务补偿不一定将系统中的数据返回到原始操作开始时的状态。相反,它会补偿在操作失败之前成功完成的步骤执行的工作。 事务补偿中的步骤顺序不一定与原始操作中的步骤完全相反。例如,一个数据存储可能对另一个数据存储区的不一致性更敏感,因此补偿事务中撤消对该存储的更改的步骤应首先发生。 在完成操作所需的每个资源上放置基于超时的短期锁,提前获取这些资源可以帮助增加整体活动成功的可能性。这项工作只有在所有资源获得后才能执行。所有操作必须在锁到期之前完成。 考虑使用比平常更宽容的重试逻辑来最小化触发补偿事务的故障。如果执行最终一致性的操作步骤失败,请尝试将该失败视为暂时异常并重复该步骤。只有在反复失败或不可恢复的情况下,才停止操作并启动事务补偿。

执行事务补偿的许多挑战与实施最终一致性的挑战相同。更多信息请参阅数据一致性入门中实现最终一致性的注意事项。

何时使用该模式

此模式仅适用于失败时必须撤消的操作。如果可能,设计解决方案避免需要事务补偿的复杂性。

案例

旅游网站让客人预订行程。单程可能包括一系列航班和酒店。 从西雅图到伦敦,然后到巴黎的客户,创建行程时可以执行以下步骤:

  1. 预订从西雅图到伦敦的F1航班座位。
  2. 预订从伦敦到巴黎F2航班的座位。
  3. 预订从巴黎到西雅图F3班机的座位。
  4. 在伦敦的H1酒店预订房间。
  5. 在巴黎的H2酒店预订客房。

这些步骤构成了最终一致的操作,尽管每个步骤都是单独的操作。因此,除了执行这些步骤之外,系统还必须记录必要的计数器操作,以便在客户决定取消行程的情况下撤消每个步骤。执行计数器操作所需的步骤之后可以作为补偿事务运行。 请注意,事务补偿中的步骤可能与原始步骤完全相反,事务补偿的每个步骤中的逻辑必须考虑到任何特定于业务的规则。例如,在航班上取消预订座位可能无法让客户完全退还所支付的任何费用。下图展示了生成事务补偿以撤销预订旅行行程的长时间运行的交易。

根据每个步骤设计补偿逻辑的方式,补偿事务中的步骤可能并行执行。 在许多业务解决方案中,单步骤的故障并不总是需要通过使用事务补偿来回滚系统。例如,如果在旅游网站场景中预订了F1,F2和F3的航班-客户无法在酒店H1预订房间,比取消航班更好的是在同一城市的不同酒店为客户预定房间。在客户仍然决定取消时(在这种情况下,事务补偿运行并撤销在F1,F2和F3航班上的预订),但决定应由客户而不是由系统做出。

相关模式和指南

以下模式和指南在实现此模式时也可能相关:

  • 数据一致性入门。补偿事务模式通常用于撤消实现最终一致性模型的操作。该文章提供了有关最终一致性的优点和权衡的信息。
  • 调度代理主管模式。介绍如何实现执行使用分布式服务和资源的业务运营的弹性系统。 有时可能需要通过使用事务补偿来撤消由操作执行的工作。
  • 重试模式。补偿事务的执行可能很昂贵,并且可以根据重试模式,实现重试失败操作的有效策略,最小化它们的使用。

results matching ""

    No results matching ""