当前位置: 首页 > 知识库问答 >
问题:

2PC与Sagas(分布式事务)

谭煜
2023-03-14

我正在发展我对分布式系统的见解,以及如何在这样的系统中保持数据一致性,其中业务事务涵盖多种服务、有限的上下文和网络边界。

我知道有两种方法用于实现分布式事务:

  • 2阶段提交(2PC)
  • 萨加斯

2PC 是一种协议,供应用程序通过平台支持透明地利用全局 ACID 事务。据我所知,它嵌入在平台中,对业务逻辑和应用程序代码是透明的。

另一方面,Sagas是一系列本地事务,其中每个本地事务都会发生变化,并保存实体以及一些指示全局事务阶段的标志,并提交更改。换句话说,事务的状态是域模型的一部分。回滚就是提交一系列“反向”事务。在任一情况下,服务发出的事件都会触发这些本地事务。

现在,什么时候以及为什么人们会使用传奇而不是2PC,反之亦然?这两者的用例和优缺点是什么?特别是,传奇的脆弱性让我感到紧张,因为反向分布式事务也可能失败。

共有3个答案

南门棋
2023-03-14

您的比较在逻辑上不一致。像Sagas这样的旧解决方案需要更多的工作来实现XA/2PC

通常,2PC 用于即时交易。通常,Sagas 适用于长期运行的事务。

这是不正确的,XA事务可以运行数周,如果您愿意,可以不超时。我使用过XA/2PC运行一周的系统,有些运行1ms。

我个人认为佐贺有能力做2PC能做的事情。相反是不准确的。

不,传奇是XA更原始的解决方案。XA是较新的解决方案。在Sagas中,需要开发样板文件来处理事务。XA将事务管理的公共元素移到了底层平台,减少了开发人员必须管理的锅炉板膨胀。

我认为Sagas是通用的,而2PC涉及平台/供应商锁定。

XA规范已经被许多供应商实施,并且非常普遍。30多年来,跨多个组织的多个平台实施2PC一直是个问题。

寿鸣
2023-03-14

我添加我的答案是为了解决sagas和2PC之间的主要区别,2PC是一个一致性模型

另一方面,Sagas是一系列本地事务,其中每个本地事务都会发生变化,并保存实体以及一些指示全局事务阶段的标志,并提交更改。

有趣的描述。这个标志到底是什么?每个节点都应该在全局事务完成后提交更改吗(这是由这个标志跟踪的)?每个节点都保持外部不可见的本地更改,直到这种情况发生?如果是这样,那么这与2PC有什么不同?如果不是这样,那么这个标志是干什么用的?

一般来说,就我的理解,一个saga就是一系列的本地事务。如果序列中的任何一个节点失败,那么流程反向,每个节点以相反的顺序产生一个补偿事务。

然而,对于这个想法,我们遇到了几个问题:第一个问题是您自己已经注意到的:如果补偿事务失败了怎么办?如果任何一步的沟通失败了怎么办?但除此之外,通过这种方法,脏读也是可能的。假设节点1成功,节点2失败。然后,我们在Node1上发出一个补偿事务。但是,如果在Node1更新之后,但在补偿事务恢复更新之前,另一个进程读取数据,该怎么办呢?潜在的不一致性(取决于您的需求)。

一般来说,saga在设计上是:最终一致和高效的(没有全局资源锁定)。如果您可以完全控制所有节点,那么saga可以变得非常一致,但这需要大量的手动(并且不明显,例如通信问题)工作,并且可能需要一些资源锁定(因此我们将失去性能)。在这种情况下,为什么不首先使用2PC呢?

另一方面,2PC在设计上具有很强的一致性,由于资源锁定,这可能会降低效率。

那么使用哪一个呢?这取决于您的要求。如果您需要强一致性,那么 2PC。如果不是,那么 saga 是一个有效的选择,可能更有效。

例 1.假设您创建了一个会计系统,用户可以在其中在帐户之间转移资金。假设这些帐户位于不同的系统上。此外,你有一个严格的要求,即余额应该始终是非负的(你不想处理隐性债务),也许有一个严格的要求,可以设定一个最大金额,不能超过(想想偿还债务的专用账户:你不能投入超过整个债务的钱)。那么 sagas 可能不是您想要的,因为由于脏读(和其他一致性现象),我们最终可能会得到超出允许范围的平衡。2PC在这里将是一个更容易的选择。

例 2.同样,你有一个会计系统。但是这次允许平衡超出范围(拥有系统的人将手动处理)。在这种情况下,也许传奇更好。因为手动处理极少数麻烦的状态可能比始终保持强一致性的成本更低。

邹誉
2023-03-14

在我的理解中(不是2PC的大用户,因为我认为它具有限制性):

  • 通常,2PC用于即时交易
  • 通常,Sagas用于长期运行的事务

使用案例很明显:

  • 2PC 允许您在一个请求中提交整个事务,跨越系统和网络的请求。假设每个参与系统和网络都遵循协议,您可以无缝提交或回滚整个事务。
  • Saga允许您将交易拆分为多个步骤,跨越很长时间(不一定是系统和网络)。

例子:

    < li>2PC:为每个收到的发票请求保存客户,而这两个请求由两个不同的系统管理。 < li>Sagas:预订由多个转机航班组成的航班行程,而每个单独的航班由不同的航空公司运营。

我个人认为佐贺有能力做2PC能做的事情。相反是不准确的。

我认为Sagas是通用的,而2PC涉及平台/供应商锁定。

更新/添加(可选读取):

我的答案已经在这里有一段时间了,我看到这个话题从那以后获得了一些牵引力。

我想为那些来到这里但不确定该走哪条路的人澄清关于这个话题的几点。

  1. Saga是一个领域建模(即技术不可知)概念,而2PC是一个特定于技术的概念,一些(可能很多)供应商都在实现它。作为类比,如果我们将域事件(裸对象)与消息代理(例如RabbitMQ)进行比较,也是一样的
  2. 如果您与实现这种协议的平台结婚,2PC可能是一个不错的选择。并非所有人都这样,因此我称之为限制。我看到人们发现了一个论点,即佐贺更具限制性,因为它更难实施,但这就像说橘子比苹果更多汁,而苹果更甜。两件不同的事情
  3. 还要考虑人的因素。有些人(开发人员、架构师)是技术极客。他们将业务逻辑或域模型称为样板代码。我属于另一组人,他们认为域模型是最有价值的代码。这种偏好也会影响Saga和2PC之间的决定,以及谁喜欢什么。我无法解释为什么你更喜欢领域驱动的思维而不是技术驱动的解决方案,因为它不适合本页,你会放弃阅读我的答案。请通过我的文章在网上找到更多信息

@freakish评论中提到了一个公平的观点:2PC更喜欢一致性,而Saga将其降级为“最终一致性”。如果您遇到一致性比可用性更重要的情况(请阅读 CAP),那么也许您确实需要像 2PC 这样的系统事务协议。否则,我建议使用Saga等商业交易。请阅读系统交易与商业交易,例如在PEAA中。

 类似资料:
  • 我知道最好使用 Saga 模式,但想想还是很有趣的: < Li > 2PC/XA分布式事务是否提供了仅从一个应用程序和一个TM与多个RM进行事务的可能性? < li >如果没有-如果每个微服务只能访问自己的数据库,如何在多个微服务之间使用2PC/XA分布式事务来提供使用2PC的能力?我很乐意看到一个例子 < li >我们是否需要将TransactionManager服务作为一个独立的微服务,在多个

  • ShardingSphereTransactionManager SPI 名称 详细说明 ShardingSphereTransactionManager 分布式事务管理器 已知实现类 详细说明 XAShardingSphereTransactionManager 基于 XA 的分布式事务管理器 SeataATShardingSphereTransactionManager 基于 Seata 的分

  • ShardingSphere-Proxy 接入的分布式事务 API 同 ShardingSphere-JDBC 保持一致,支持 LOCAL,XA,BASE 类型的事务。 XA 事务 ShardingSphere-Proxy 原生支持 XA 事务,默认的事务管理器为 Atomikos。 可以通过在 ShardingSphere-Proxy 的 conf 目录中添加 jta.properties 来定

  • 通过 Apache ShardingSphere 使用分布式事务,与本地事务并无区别。 除了透明化分布式事务的使用之外,Apache ShardingSphere 还能够在每次数据库访问时切换分布式事务类型。 支持的事务类型包括 本地事务、XA事务 和 柔性事务。可在创建数据库连接之前设置,缺省为 Apache ShardingSphere 启动时的默认事务类型。

  • 背景 数据库事务需要满足 ACID(原子性、一致性、隔离性、持久性)四个特性。 原子性(Atomicity)指事务作为整体来执行,要么全部执行,要么全不执行。 一致性(Consistency)指事务应确保数据从一个一致的状态转变为另一个一致的状态。 隔离性(Isolation)指多个事务并发执行时,一个事务的执行不应影响其他事务的执行。 持久性(Durability)指已提交的事务修改数据会被持久

  • 单文档原子性可满足大多数业务需求 在 MongoDB 中,对单个文档的操作是原子操作。 由于 MongoDB 文档数据模型,一个文档中通过嵌入式的文档和数组来表示传统关系数据库模型中的一对一、一对多关系,而不是通过文档之间的复杂关系来描述业务需求中的一对一、一对多关系。 所以单文档原子性可以满足实际生产中大多数关于事务的需求。 对于需要对多个文档(在单个或多个集合中)进行原子读写的情况,Mongo