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

问题描述 投票:5回答:4

我读了一篇帖子说:

我们不能在分布式环境中实现微服务中的两阶段提交等传统的事务系统。

我完全赞同这一点。

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

提前致谢

java microservices distributed-system distributed-transactions 2phase-commit
4个回答
3
投票

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

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


1
投票

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

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

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

这些问题很难在具有专用网络的共址服务器上的一些紧密耦合的服务之间进行管理。在更加异构的环境中,具有更多服务器和更高的延迟(这是微服务部署的特征),它变得更加困难。


0
投票

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

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

您无法扩展系统和整点,服务应该是独立的,并且可以扩展可扩展性。

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


0
投票

有些事情需要注意,并给出一些背景知识:

  1. 在大多数情况下,微服务通过HTTP(无状态协议)进行交互,因此全局/ XA事务不适用/不可能。
  2. 确切一旦语义不可能,你应该去“至少一次”。这意味着所有服务都应该是幂等的。
  3. 为什么不能在这样的设置中实现“完全一次”语义的一个很好的例子是http连接在返回客户端的途中经常丢失。这意味着通过POST,服务器的状态已更改,而客户端收到超时错误。
  4. 在微服务的边界内,你可以很好地使用它们。正如您提到的Kafka,您可以非常轻松地使用(从1个主题)并生成(到1个或多个主题)单个原子/全部或全部操作(完全一次语义)。
  5. 但是,如果您希望通过http进行交互的微服务之间的全局和长期运行事务是唯一可行的选项(如果您使用谷歌,您可能会通过http看到全局事务,但对于生产系统而言只是忽略它们),就是设计最终的一致性。简而言之,这意味着,永久性地重试可恢复的错误(这本身就是整章)并暴露补偿端点或产生补偿事件,最终将修复不可恢复的错误。看看sagas patternNarayana Transaction Manager有很好的Sagas支持和良好的产品比较。
  6. 分布式系统非常复杂,您应该有理由寻求这样的解决方案。如果你去分发,你的monolith可以安全地委托给你的事务管理器的操作必须由开发人员/架构师处理:-)。
© www.soinside.com 2019 - 2024. All rights reserved.