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

Sam*_*Sam 6 java 2phase-commit distributed-system distributed-transactions microservices

我读了一篇文章说:

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

我完全同意这一点。

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

提前致谢

Sap*_*asu 10

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

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


Vas*_*lis 5

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

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