为什么两阶段提交不适用于微服务架构?

时间:2019-03-19 20:42:30

标签: java microservices distributed-system distributed-transactions 2phase-commit

我读了一篇帖子说:

  

我们无法在微服务中实现传统的交易系统,例如两阶段提交   在分布式环境中。

我完全同意。

但是,如果有人可以解释此问题的确切原因,那就太好了。 如果我要通过微服务实现两阶段提交,将会遇到什么问题?

预先感谢

5 个答案:

答案 0 :(得分:2)

避免两阶段提交的主要原因是,事务协调器是一种独裁者,因为它告诉所有其他节点要做什么。通常,事务协调器嵌入在应用程序服务器中。在第一阶段或准备阶段之后,事务协调器或应用程序服务器关闭时,就会发生问题。现在,参与节点不知道该怎么办。他们不能承诺,因为他们不知道其他人是否对协调员回答“否”,也无法回滚,因为其他人可能对协调员说“是”。因此,直到协调员在15分钟后(例如)回来并完成第二阶段,参与的数据存储将保持锁定状态。这抑制了可扩展性和性能。在第一阶段之后协调器的事务日志损坏时,会发生更糟的事情。在这种情况下,数据存储将永远保持锁定状态。即使重新启动进程也无济于事。唯一的解决方案是手动检查数据以确保一致性,然后删除锁。这些事情通常发生在高压情况下,因此肯定是巨大的运营开销。因此,传统的两阶段提交不是一个好的解决方案。

但是,这里应该注意的是,某些现代系统(例如Kafka)也实现了两阶段提交。但这与传统解决方案的不同之处在于,这里的每个经纪人都可以充当协调者,因此Kafka的领导者选举算法和复制模型可以缓解传统模型中提到的问题。

答案 1 :(得分:1)

这里的“我们不能”的意思是“这是一个坏主意,我不想这样做,如果我承认这种可能性,那么我可能无法说服您不坚持”。

您当然可以跨微服务实现两阶段提交,但是:

  • 两阶段提交要求在每个可以参与交易的服务中进行大量开发工作,
  • 这会导致客户端之间的大量争用,随着服务器之间的通信延迟而增加;和
  • 所有涉及的服务必须在很多协议,配置,部署和其他细节上达成一致,这些细节决定了两阶段提交的实际工作方式。

这些问题很难在具有专用网络的同位服务器上的几个紧密耦合的服务中进行管理。在具有更多服务器和更高延迟的异构环境中,这是微服务部署的特征,这变得越来越困难。

答案 2 :(得分:1)

我认为并不是我们不能为微服务实现 XA 或 2PC,而是基于 HTTP 的 API 世界在政治上尚未被接受。在较旧的应用程序中,组件可能代表一组更大的复杂业务逻辑步骤,但也代表跨度、硬件、地理、组织和技术。即我的业务组件可以分布在多个公司中,每个公司都有不同的用户界面。集成所有这些支持的分布式事务 (2PC) 以及传播用户身份等的网络协议。

这有官僚作风和遗留问题。多个可互操作平台支持的标准化分布式事务可以追溯到 80 年代。 IT 非常受时尚驱动,如果您过分提倡此类功能,您的工作场所会发生什么。

注意:关于如果控制节点关闭会发生什么的问题。在传统应用程序中,如果提交应用程序的组件在提交过程中死亡,事务最终会超时并在每个组件上回滚。在某些情况下,可以使用可恢复的事务功能。如果提交者在超时之前恢复,它将恢复事务并继续提交。我们在企业应用程序中经常看到这种情况,如果应用服务器出现故障,它会恢复正在进行的工作。

虽然我心情不好:) - 一些权威人士声称 XA 必须在单一平台上实现,比如 JTA。我从来没有发现这是真的,XA 一直在为我无缝地跨数据库、应用服务器和大型机工作)

答案 3 :(得分:0)

微服务的整体思想是松散耦合和独立的服务。由于2pc意味着我们有2个阶段来提交事务。控制节点将驱动事务,所有其他节点首先响应它们已准备好,在第二阶段,它们都将根据阶段1提交或回滚。

如果控制节点关闭,会发生什么?当其他任何节点发生故障时会发生什么?由于这个限制,您的整个交易无法通过。在分布式事务中,您的节点可以位于不同的数据中心或区域中。响应最慢的节点将在其他节点继续前进时将其保持在等待状态。因此原子性会影响性能。

您无法扩展系统,整个服务应该独立且可扩展的要点丢失了。

2pc不是错误的答案,但是在大多数情况下,我们认为最终的一致性。如果您的系统需要高度的一致性,则可以选择2pc。

答案 4 :(得分:0)

需要注意的一些事情,并提供一些背景知识:

  1. 在大多数情况下,微服务通过HTTP(无状态协议)进行交互,因此,全局/ XA事务不适用/不可能。
  2. 只有一次不可能使用语义,因此您应该“至少一次”。这意味着所有服务都应是幂等的。
  3. 为什么不能在这种设置中实现“仅一次”语义的一个很好的例子是,在返回客户端的途中,HTTP连接经常丢失。这意味着通过POST,服务器的状态已更改,而客户端收到超时错误。
  4. 在微服务的边界内,您可以很好地使用它们。正如您提到的Kafka一样,您可以很容易地消耗(从1个主题开始)并产生(至1个或多个主题)单个原子/全有或全无操作(恰好是一次语义)。
  5. 但是,如果您希望通过http进行交互的微服务之间的全局事务和长期运行的事务是唯一可行的选择(如果您使用google可能会通过http进行全局事务,但是对于生产系统则忽略它们)是为了最终一致性而设计。简而言之,这意味着永远尝试可恢复的错误(这本身就是一整章),并公开补偿端点或产生补偿事件,这些事件最终将修正不可恢复的错误。签出sagas patternNarayana Transaction Manager拥有良好的Sagas支持和良好的产品比较。
  6. 分布式系统非常复杂,您应该有理由选择这种解决方案。如果您是分布式的,则您的整体程序可以安全地委派给事务管理器的操作将必须由开发人员/架构师处理:-)。