2PC 作为分布式事务补偿的解决方案

2PC as solution for compensation in distributed transactions

我正在比较 Saga 和两阶段提交

我对 2PC 的分析是,如果在准备阶段我将数据保持在挂起状态,我可以避免锁定我的事务并在最后阶段提交我的更改。

显然成本是 Saga 模式的 2 倍,但在某些情况下 2PC 可能比 Saga 更有趣。

例如:作为交易的一部分,发送了一封电子邮件,使用 Saga 是不可能恢复的,万一失败了,但是使用 2PC 这是可能的(假设这对我的业务很重要)。

我最后的疑惑是,有没有像我上面写的2PC这样的模式? or no,没有其他模式只是2PC的改编。

PS: 在public之前,我阅读了一些文章并研究了另一个问题。

两阶段提交协议/分布式事务的主要优点是编程模型或多或少等同于本地事务,除了额外资源的征用和最终 prepare/commit阶段(通常由框架处理)。 ACID 属性仍然完全适用,数据一致性由基础架构而非开发人员处理。

一个主要缺点是两阶段提交协议在基础设施要求和组件故障情况下的复杂性。需要分布式事务管理器,以便将决策写入稳定存储,并且 commits/rollbacks 可以在组件出现故障时由 TM 执行。 只要事务未提交 and/or 回滚,准备好的事务可能会涉及锁定。这尤其成问题,因为那些所谓的有疑问的交易必须由 TM 处理,这可能会导致严重的延迟,可能会影响其他(甚至本地)交易 and/or 数据库管理后台进程。

性能是另一方面。根据写入流量,需要维护事务日志的事务管理器可能成为瓶颈。

系统备份也变得更具挑战性。分布式事务的整个思想是数据库的视图保持一致。在备份的情况下,创建所涉及的每个数据库的备份将不允许您重新创建备份,除非您确保每个数据库的恢复是根据时间戳或更好的本地事务完成的特定时间点ID。这通常称为分布式时间点恢复,涉及阻止所有新的分布式事务、从每个单独的数据库读取当前事务 ID 并将该信息与单独的备份一起存储。在恢复时,可以根据记录的事务ID将数据库恢复到时间点。此外,TM 事务日志必须是备份策略的一部分。

Saga 模式不提供保证一致性的基础设施,编程模型必须考虑一致性问题。在分布式事务的情况下,金融事务将涉及一个分布式事务,该分布式事务减去数据库 A 中的金额并添加数据库 B 中的金额,其结果将随着分布式事务的提交而变得可见。 在 Saga 的情况下,相同的金融交易可能会在数据库 A 中创建一个待处理的交易记录,并在数据库 B 中创建一个待处理的交易记录,一旦数据库 B 的服务成功,其结果将通过两个确认这些交易记录的单独交易变得可见向服务 A 报告执行完成。或者,专用编排器可以通过与每个单独的服务通信来处理事务。 Saga 中的回滚触发补偿事务,撤消已经提交的工作。

在很多方面,Saga 通过要求编程模型处理一致性问题来模拟分布式事务。数据库模式必须通过将状态或版本信息与数据库 objects/rows 相关联来考虑一致性,以再次创建完全或最终一致的数据库视图。所有这些都必须由开发人员(或框架,如果可用)完成,而不是数据库基础设施。

Saga 购买的是灵活性,因为可以根据所需的实际一致性约束来解决每个单独的一致性问题。在存在的每个用例中通常不需要完全一致性。这可能意味着更高的性能和可扩展性,因为一致性要求也可以扩展并且通常不涉及集中式 TM。 它还在基础设施方面购买了灵活性,因为所涉及的组件不必支持分布式事务(大多数 NOSQL 数据库不支持)。这直接影响可伸缩性,因为数据库的选择会影响最终系统的可伸缩性。 通常可以在不涉及其他数据库的情况下创建备份,因为各个系统已经必须在更高级别处理不一致问题。

分布式事务所需的紧密耦合会严重限制可伸缩性、性能和可用性。服务越大,就越不可能使用分布式事务来保证所有组件之间的一致性。许多大规模部署都有数百个微服务,这些微服务大多彼此独立,仅使用定义明确的 API 进行协作。服务 A 的可用性并不一定会影响服务 B,这是一件好事。或者或除此之外,这些微服务操作的数据通常根据明确定义的标准(例如客户 a-d,...)进行分区,以创建实际上可以作为一个单元进行管理的实例,并允许水平可扩展性和高可用性.在整个服务中使用分布式事务会有点违背目的。

关于您提到的具体场景:发送邮件是一个影响外部系统的动作,无法回滚。因此,对于 Saga 和分布式事务,只有在所有其他步骤都成功后才能发送电子邮件。