微服务架构中的分布式事务,如何处理超时和失败的提交

Posted

技术标签:

【中文标题】微服务架构中的分布式事务,如何处理超时和失败的提交【英文标题】:distributed transactions in microservice architecture, how to handle timeouts and failed commits 【发布时间】:2017-08-31 19:36:51 【问题描述】:

假设您有一个服务A,它是大型微服务架构的一部分,这些服务通过 REST API 或通过涉及某些代理 (RabbitMQ) 的消息传递相互通信。服务 A 暴露 REST 端点,该端点需要与某些第 3 方服务(因此使用不在我们架构中的服务)通信并在那里创建一些东西,当服务 A 收到来自第 3 方的响应时,那里一切顺利,它应该将该响应中的一些数据保存在自己的数据库中。

考虑到第 3 方不提供任何幂等机制,解决以下问题的最佳方式是什么。

    第 3 方的创建顺利,但服务中的 DB 写入失败 A。这会导致状态不一致,您在第 3 方创建了一些内容,但您自己的数据库中不需要有关它的数据。

    您收到来自第 3 方的超时,因此您不能只是重复调用,因为他们没有提供任何幂等机制。如果您重复调用,您可能会以两个(或更多)创建的资源结束,而不是一个。

问题编号 1. 可以通过任何重试机制来解决任何重试 DB 调用的次数。这种方法的问题在于,如果重复数据库调用的服务A 实例突然关闭。

据推测,更好的方法是该服务在第 3 方成功创建后,发布有关成功创建的 RabbitMQ 消息。该服务将侦听该消息,并在收到消息时进行 DB 调用。拥有良好的重试机制并利用 ACKing 消息,可以解决What if service instance goes down suddenly 的问题。 所以在这个解决方案中,服务是它自己的消息的发布者和消费者。 有更好的主意吗?此解决方案还将引入 最终一致性,因为 API 调用者(正在调用服务 A 端点的人)将在第 3 方成功创建后立即收到响应,但在此之前任何东西都保存在服务数据库中(API 客户端实际需要什么)

超时问题呢? 在这种情况下如何处理来自第 3 方的超时?。我认为没有什么比发出 GET 调用来检查他们是否创建了某些东西更好的了。再一次,GET 调用可能会失败,但它可以重复直到成功。这里还有一个边缘用例是如果服务在发出 GET 调用时出现故障。

【问题讨论】:

您应该考虑放弃分布式事务和 2 阶段提交。在云环境中或在涉及第三部分代码/基础设施时进行设置和处理是一场噩梦。 2PC 的替代方案是最终一致性和补偿事务。 @Bishoy 我在这里使用或提议 2PC 的方式是什么?正如我所说,至少在我看来,我在这里提出了涉及代理和最终一致性的异步处理。 【参考方案1】:

正确设置容错并不容易。我记得他们为 netflix 堆栈实现了一个专用模块:hystrix。也许这会对你有所帮助。

【讨论】:

使用 NServiceBus 我会使用名为 saga docs.particular.net/nservicebus/sagas 和发件箱 docs.particular.net/nservicebus/outbox 的两个功能来解决这种情况

以上是关于微服务架构中的分布式事务,如何处理超时和失败的提交的主要内容,如果未能解决你的问题,请参考以下文章

分布式事务的 6 种解决方案,写得非常好!

分布式服务的事务如何处理?比如dubbo,服务与服务之间的事务怎么处理比较好,现在有没有开源的解决方案?

架构装逼必备词汇(转某大牛微博)

分布式事务的 6 种解决方案,写得非常好!

如何处理SQL Server事务复制中的大事务操作

你们公司是如何处理分布式事务的?