17

我读过一篇文章说:

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

我完全同意这一点。

但是,如果这里有人可以解释其确切原因,那就太好了。如果我使用微服务实现两阶段提交,我将面临哪些问题?

提前致谢

4

6 回答 6

11

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

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

于 2019-03-20T01:12:51.187 回答
5

需要注意的一些事项并提供一些背景信息:

  1. 在大多数情况下,微服务通过 HTTP(一种无状态协议)进行交互,因此全局/XA 事务不适用/不可能。
  2. 恰好一次语义是不可能的,你应该选择“至少一次”。这意味着所有服务都应该是幂等的。
  3. 为什么在这种设置中无法实现“恰好一次”语义的一个很好的例子是,http 连接在返回客户端的过程中经常丢失。这意味着通过 POST,服务器的状态发生了变化,而客户端收到了超时错误。
  4. 在微服务的边界内,您可以很好地使用它们。正如您提到的 Kafka,您可以很容易地使用(从 1 个主题)并产生(到 1 个或更多主题)单个原子/全有或全无操作(恰好一次语义)。
  5. 但是,如果您想要通过 http 交互的微服务之间的全局且长期运行的事务,唯一实用的选择(如果您使用 google,您可能会看到通过 http 的全局事务,但对于生产系统,只需忽略它们),就是设计最终一致性。简而言之,这意味着,永远重试可恢复的错误(这本身就是一整章)并暴露补偿端点或产生最终将修改不可恢复错误的补偿事件。查看sagas 模式Narayana 事务管理器具有良好的 Sagas 支持和良好的产品比较。
  6. 查看提供 XA 事务替代方案的相关微服务模式(您可能将其视为全局事务或 2 阶段提交/2PC),例如提供良好的“至少一次语义”的事务发件箱事件溯源。
  7. 分布式系统非常复杂,您应该有理由采用这样的解决方案。如果你去分布式,你的单体可以安全地委托给你的事务管理器的操作将必须由开发人员/架构师处理:-)。
  8. 此外,大多数非 SQL 数据库/系统根本不支持 XA 事务(即全局事务),因为它们显着降低了处理速度。
于 2019-03-20T10:23:37.313 回答
2

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

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

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

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

于 2019-03-20T16:57:32.657 回答
1

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

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

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

2pc 不是错误的答案,但在大多数情况下,我们会考虑最终的一致性。如果您的系统需要强一致性,那么 2pc 可能是选项。

于 2019-03-19T21:05:37.560 回答
1

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

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

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

当我在咆哮时 :) -一些专家声称 XA 必须在单一平台上实现,比如 JTA。我从来没有发现这是真的,XA 一直为我在数据库、应用程序服务器和大型机之间无缝地工作)

于 2021-02-17T19:45:26.953 回答
0

我将详细阐述 Vassilis 的第一点“在大多数情况下,微服务通过 HTTP(一种无状态协议)进行交互,因此全局/XA 事务不适用/不可能。” 作为在微服务领域不使用 2-PC 的最正当理由。

微服务架构带来了应用程序/代码级别的分离,每个微服务在其单独的进程和自己的数据库中运行(每个服务模式的数据库)。每个微服务负责自己的本地事务。只有当所有参与的服务都在单个服务器进程内运行但连接到不同的(分片)数据库或事务性资源(如消息中间件)时,才有可能使用 2-PC。

于 2021-10-17T13:51:32.727 回答