代码之家  ›  专栏  ›  技术社区  ›  Tuomas Toivonen

2PC vs Sagas(分布式事务)

  •  54
  • Tuomas Toivonen  · 技术社区  · 7 年前

    我正在深入了解分布式系统,以及如何跨此类系统维护数据一致性,其中业务事务涉及多个服务、有界上下文和网络边界。

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

    • 2阶段提交(2PC)
    • 传奇故事

    2PC是应用程序用于 透明地 在平台的支持下利用全局ACID事务。据我所知,它嵌入到平台中,对业务逻辑和应用程序代码是透明的。

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

    现在,什么时候,为什么一个人会在2个以上使用传奇,反之亦然?两者的使用案例和优缺点是什么?尤其是传奇故事的脆弱性让我感到紧张,因为反向分布式事务也可能失败。

    3 回复  |  直到 7 年前
        1
  •  61
  •   Tengiz    3 年前

    根据我的理解(因为我认为2PC有局限性,所以不是2PC的大用户):

    • 通常,2PC用于 立即的 交易。
    • 通常,传奇是 长期运行 交易。

    之后,用例很明显:

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

    例子:

    • 2PC:为每个收到的发票请求保存客户,而这两个请求都由两个不同的系统管理。
    • 传奇:预订由多个联程航班组成的航班行程,而每个航班由不同的航空公司运营。

    我个人认为Saga能够做到2PC所能做到的。反面不准确。

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

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

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

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

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

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

        2
  •  1
  •   Chris    3 年前

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

    通常,2PC用于即时交易。通常,传奇是 长时间运行的事务。

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

    我个人认为Saga能够做到2PC所能做到的。反面不准确。

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

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

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

        3
  •  1
  •   freakish    3 年前

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

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

    有趣的描述。这面旗子到底是什么?是否每个节点都应该在全局事务完成后提交更改(并通过此标志跟踪)?在发生这种情况之前,每个节点都保持本地更改对外不可见?如果是这样的话,那么这与2PC有什么不同?如果不是这样的话,那么这个标志到底是为了什么?

    一般来说,据我所知,传奇是一系列本地交易。如果序列中的任何节点出现故障,那么流将被反转,并且每个节点以相反的顺序生成一个补偿事务。

    然而,在这种想法下,我们遇到了几个问题:第一个问题是您自己已经注意到的问题:如果补偿事务失败怎么办?如果任何一步的通信都失败了怎么办?但还有更多,通过这种方法,脏读是可能的。假设Node1成功,Node2失败。然后,我们在Node1上发出一个补偿事务。但如果另一个进程在Node1更新之后但在补偿事务恢复更新之前读取数据,会怎么样?潜在的不一致性(取决于您的要求)。

    一般来说,传奇是:通过设计,最终是一致和高效的(没有全局资源锁定)。如果您对所有节点都有完全的控制权,那么可以使saga具有很强的一致性,但这需要大量的手动操作(并且不明显,例如通信问题),并且可能需要一些资源锁定(因此我们将失去性能)。既然如此,为什么不先用2PC呢?

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

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

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

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