Microservices 如何在分布式事务期间锁定对象

Microservices 如何在分布式事务期间锁定对象,microservices,distributed-transactions,Microservices,Distributed Transactions,我一直在读微服务和分布式事务。大多数文章都讨论了两阶段提交或Saga模式,但没有详细介绍对象是如何锁定的,这样其他人就无法在事务尚未完成时访问该数据 如果我有客户服务和订单服务,并且我发起请求锁定客户资金,直到订单处理完毕。在分布式系统中,这是如何实现的 在DB中,是否可以显式锁定一行,然后另一个请求发出并解锁该行,或者这是使用customers表上的锁定字段实现的,第一个事务将其设置为锁定,订单完成后,返回并将其设置为解锁或清空该行 如果在微服务世界中有一些代码示例非常好,那么事务边界就在服务

我一直在读微服务和分布式事务。大多数文章都讨论了两阶段提交或Saga模式,但没有详细介绍对象是如何锁定的,这样其他人就无法在事务尚未完成时访问该数据

如果我有客户服务和订单服务,并且我发起请求锁定客户资金,直到订单处理完毕。在分布式系统中,这是如何实现的

在DB中,是否可以显式锁定一行,然后另一个请求发出并解锁该行,或者这是使用customers表上的锁定字段实现的,第一个事务将其设置为锁定,订单完成后,返回并将其设置为解锁或清空该行


如果在微服务世界中有一些代码示例非常好,那么事务边界就在服务中。服务依赖于最终的一致性。因此,在您的示例中,订单服务将根据应用程序语义和规模要求(如从客户y中为订单z扣除x金额)发送同步或异步请求

客户服务将在事务中对客户记录执行操作,并将响应返回给客户,如订单z成功处理或订单z处理失败

然后,订单服务可以根据收到的响应触发订单的确认/失败过程

应用程序通常在可用性和强一致性之间进行选择。大多数基于微服务的场景要求可用性和高可扩展性,而不是强一致性,这意味着服务之间的通信是异步的,最终实现一致状态

大多数文章都讨论了2阶段提交或Saga模式,但没有 详细说明如何锁定对象,以使其他对象无法访问 当事务尚未完成时,该数据将丢失

2PC被定义为阻塞。这意味着,如果管理2PC事务的事务管理器出现故障,则无法解决2PC问题。事务管理器是一个单点故障。 如果您确保重新启动失败的事务管理器,则即使2PC协议也会被称为阻塞,您可以确保事务管理器可用,并且解决方案不会被阻塞

然后2PC使用锁。它们是议定书的基本要素。事务管理器与参与者-资源进行通信。参与者是数据库。当2PC开始运行时,调用prepare意味着数据库对参与事务的所有行进行持久锁定。当事务管理器调用commit时,此锁被释放。 重要的是要理解2PC之前的事务不是持续的。它存储在内存中。在调用prepare之后,事务状态被持久存储,直到调用commit,此时协议可能会被不可用的事务管理器阻止-锁是持久的,系统等待事务管理器释放它

这是关于从2PC角度锁定的。但从数据库的角度来看,存在事务锁。 当您更新数据库中的一行时,事务将被存储在内存中。此时,数据库需要确保并发更新不会损坏您的数据。一种方法是锁定行,不允许并发更新。 但是,在这些情况下,大多数数据库不锁定行(默认情况下,依赖于隔离级别),因为它们使用快照隔离MVCC。这尤其意味着该行被乐观地锁定,并且数据库允许其他事务更新该行

但是!2件准备工作不能乐观地进行。当数据库回复“OK”以准备来自事务管理器的请求时,行被锁定

另外,您无法手动管理此锁定。如果你试图这样做,你就破坏了2%的一致性保证

在您的示例中,有一个客户服务和一个订单服务。当2PC事务跨越两个服务时。然后客户更新数据库,订单服务也更新数据库。数据库中仍有正在运行的事务。然后请求完成,事务管理器命令正在进行的事务提交。它运行2PC。它在customer service db事务上调用prepare,然后在order service事务上调用prepare,然后调用commit

如果您使用saga模式,那么saga将跨越这两个服务。从事务的角度来看,客户服务在飞行中创建一个数据库事务,并立即提交它。然后,调用转到订单服务,在那里也会发生同样的情况。当请求完成时,会检查是否一切正常。当一个足总 ilure调用了一个补偿回调

从易用性的角度来看,故障是个麻烦。对于saga,您需要自己在回调方法中维护故障解决方案。对于2PC,故障解决由回滚调用自动处理

注:我试图在这里总结2PC:
我不确定这个解释是否足够理解,但你可以试着检查一下。你可以让我知道错误的解释。谢谢。

这回答了你的问题吗?