两阶段提交协议/分布式事务的主要优点是编程模型或多或少等同于本地事务,除了征用额外资源和最后的准备/提交阶段(即通常由框架处理)。 ACID 属性仍然完全适用,数据一致性由基础架构而非开发人员处理。
一个主要缺点是两阶段提交协议在基础设施要求和组件故障情况下的复杂性。需要一个分布式事务管理器,以便将决策写入稳定的存储,并且在组件故障的情况下,TM 可以执行提交/回滚。
准备好的事务可能涉及只要事务尚未提交和/或回滚就持有的锁。这尤其成问题,因为那些所谓的不确定事务必须由 TM 处理,这可能会导致严重的延迟,可能会影响其他(甚至本地)事务和/或数据库管理后台进程。
性能是另一个方面。根据写入流量,需要维护事务日志的事务管理器可能会成为瓶颈。
系统备份也变得更具挑战性。分布式事务的整个想法是数据库的视图保持一致。在备份的情况下,创建所涉及的每个数据库的备份将不允许您重新创建它,除非您确保每个数据库的还原都基于时间戳或更好的本地事务完成到特定时间点ID。这通常称为分布式时间点恢复,涉及阻止所有新的分布式事务、从每个单独的数据库读取当前事务 ID 并将该信息与单独的备份一起存储。在恢复时,可以根据记录的事务ID将数据库恢复到时间点。此外,TM 事务日志必须是备份策略的一部分。
Saga 模式不提供保证一致性的基础设施,编程模型必须考虑一致性问题。在分布式事务的情况下,金融事务将涉及一个分布式事务,该事务减去数据库 A 中的金额并添加数据库 B 中的金额,其结果将随着分布式事务的提交而变得可见。
在 Saga 的情况下,相同的金融交易可能会在数据库 A 中创建待处理交易记录,在数据库 B 中创建待处理交易记录,一旦数据库 B 的服务成功,两个单独的交易确认这些交易记录的结果将变得可见向服务 A 报告执行完成。或者,专用编排器可以通过与每个单独的服务通信来处理事务。 Saga 中的回滚会触发补偿事务,以撤消已提交的工作。
在许多方面,Saga 通过要求编程模型处理一致性问题来模拟分布式事务。数据库模式必须通过将状态或版本信息与数据库对象/行相关联来考虑一致性,以再次创建完全一致或最终一致的数据库视图。所有这些都必须由开发人员(或框架,如果可用)完成,而不是数据库基础架构。
Saga 购买的是灵活性,因为每个单独的一致性问题都可以根据所需的实际一致性约束来解决。在每个单独的用例中通常不需要完全一致性。这可能意味着更高的性能和可扩展性,因为一致性要求也可以扩展,并且通常不涉及集中式 TM。
它还购买了基础设施方面的灵活性,因为所涉及的组件不必支持分布式事务(大多数 NOSQL 数据库不支持)。这直接影响可伸缩性,因为数据库的选择会影响结果系统的可伸缩性。
通常可以在不涉及其他数据库的情况下创建备份,因为各个系统已经不得不在更高级别上处理不一致。
分布式事务所需的紧密耦合会严重限制可扩展性、性能和可用性。服务越大,分布式事务用于保证所有组件一致性的可能性就越小。许多大规模部署都有数百个微服务,这些微服务大多相互独立,仅使用定义良好的 API 进行协作。服务 A 的可用性不一定会影响服务 B,这是一件好事。或者或除此之外,这些微服务操作的数据通常根据明确定义的标准(例如客户 a-d,...)进行分区,以创建实际上可以作为一个单元进行管理并允许水平可扩展性和高可用性的实例.在整个服务中使用分布式事务有点违背目的。
关于您提到的特定场景:发送电子邮件表示影响外部系统且无法回滚的操作。因此,对于 Saga 和分布式事务,只有在所有其他步骤都成功后才能发送电子邮件。