微服务分布式事务

栏目: 后端 · 发布时间: 6年前

内容简介:当微服务架构将单体系统分解为一个个单一微服务时,它可能破坏了事务。这意味着单体系统中的本地事务将分布到按顺序调用的多个服务中。以下是使用本地事务的单体系统的客户订单示例:在上面的客户订单示例中,如果用户将Put Order 操作发送到单体系统,则单体系统将创建一个作用于多个数据库表上的本地数据库事务。如果其中任何一个步骤失败,则整个事务回滚。这种ACID(原子性,一致性,隔离性,耐久性)是由数据库系统保证。

当微服务架构将单体系统分解为一个个单一微服务时,它可能破坏了事务。这意味着单体系统中的本地事务将分布到按顺序调用的多个服务中。

以下是使用本地事务的单体系统的客户订单示例:

微服务分布式事务

在上面的客户订单示例中,如果用户将Put Order 操作发送到单体系统,则单体系统将创建一个作用于多个数据库表上的本地数据库事务。如果其中任何一个步骤失败,则整个事务回滚。这种ACID(原子性,一致性,隔离性,耐久性)是由数据库系统保证。

当我们分解这个系统中,我们创建了两个 CustomerMicroservice和 OrderMicroservice微服务,各自具有单独的数据库。这是一个带有微服务的客户订单示例:

微服务分布式事务

当 Put Order请求来自用户时,将调用两个微服务,并将修改操作应用到他们自己的数据库中。由于事务现在跨多个数据库,因此它现在被视为 分布式事务。

在单体系统中,我们有一个数据库系统来确保ACIDity。那么在分布式如何保证?

我们如何保证事务的原子性?(ACID的原子性)

在数据库系统中,原子性意味着在事务中 所有步骤都要么都完成或要么全部没有完成。 默认情况下,基于微服务的系统没有全局事务协调器。在上面的示例中,如果CreateOrder方法失败,我们如何回滚我们应用的更改CustomerMicroservice?

我们是否针对并发请求隔离用户操作了?( ACID的隔离性)

如果一个对象是由两个事务同时操作,如何保证它们之间的隔离?在上面的示例中,一旦UpdateCustomerFund成功但仍在等待响应 CreateOrder,那么当前客户基金的请求是否会返回更新后的金额?

可能的解决方案

上述问题对于基于微服务的系统很重要,否则,无法判断事务是否已成功完成。以下两种模式可以解决问题:

2pc(两阶段提交)

2pc广泛用于数据库系统。在某些情况下,您可以使用2pc应用到微服务。小心点; 并非所有情况都适合2pc,事实上,2pc在微服务架构中被认为是不切实际的。

那么什么是两阶段提交?

正如其名称提示,2pc有两个阶段:准备阶段和提交阶段。在准备阶段,将要求所有微服务准备一些可以原子方式完成的数据更改。一旦准备好所有微服务,提交阶段将要求所有微服务进行实际更改。

通常,需要有一个全局协调器来维护事务的生命周期,协调器需要在准备和提交阶段调用微服务。

以下是客户订单示例的2pc实现:

微服务分布式事务

在上面的示例中,当用户发送下订单请求时,Coordinator将首先创建包含所有上下文信息的全局事务。然后它会告诉CustomerMicroservice准备用创建的事务更新客户资金。该CustomerMicroservice会再检查,例如,如果客户有足够的资金来继续进行交易。一旦 CustomerMicroservice可以执行更改,它将锁定对象以免进一步更改并告知Coordinator它已准备好。在创建订单时会发生同样的事情OrderMicroservice。一旦Coordinator确认所有微服务都准备好应用他们的更改,它就会要求他们通过请求提交事务来应用他们的更改。此时,所有对象都将被解锁。

如果在任何时候单个微服务无法准备,Coordinator则将中止事务并开始回滚过程。以下是客户订单示例的2pc回滚图:

微服务分布式事务

在上面的例子中,由于CustomerMicroservice某种原因未能做好准备,但OrderMicroservice已经回复说它准备创建订单。在Coordinator将请求中止对OrderMicroservice的事务,让OrderMicroservice回滚所作的任何更改和解锁的数据库对象。

使用2pc的好处

2pc是一种非常强大的一致性协议。首先,准备和提交阶段保证事务是原子的。事务将以所有微服务成功返回或所有微服务都没有改变而结束。其次,2pc允许读写隔离。这意味着在协调器提交更改之前,数据库字段上的更改是相互不可见的。

使用2pc的缺点

虽然2pc已经解决了这个问题,但是对于许多基于微服务的系统并不是真的有用,因为2pc是同步的(阻塞)。协议将需要锁定所有在事务完成之前更改的对象。在上面的示例中,如果客户下订单,则将为客户锁定“基金”字段。这可以防止客户申请新订单。这是有道理的,因为如果“准备好的”对象在声称它已“准备好”之后发生了变化,那么提交阶段可能无效。

这不是很好。在数据库系统中,事务通常在50毫秒内快速正常完成。但是,微服务在RPC调用方面存在长时间延迟,尤其是在与外部服务(如支付服务)集成时。锁可能成为系统性能瓶颈。此外,当每个事务请求锁定另一个需要的资源时,可能有两个事务相互锁定(死锁)。

Saga模式

Saga模式是另一种广泛使用的分布式事务模式。它与2pc不同,后者是同步的。Saga模式是异步和反应性的。在Saga模式中,分布式事务由所有相关微服务上的异步本地事务完成。微服务通过事件总线相互通信。

以下是客户订单示例的Saga模式图:

微服务分布式事务

在上面的示例中,OrderMicroservice接收订单的请求。它首先启动本地事务以创建订单,然后发出OrderCreated事件。CustomerMicroservice将监听此事件,接受到此事件后并更新客户资金。如果从资金中成功进行扣减,则会发出一个事件CustomerFundUpdated,表示交易结束。

如果任何微服务无法完成其本地事务,则其他微服务将运行补偿事务以回滚更改。以下是补偿交易的Saga模式图:

微服务分布式事务

在上面的示例中,由于UpdateCustomerFund某种原因失败,然后它发出了一个CustomerFundUpdateFailed事件。在OrderMicroservice该事件监听并启动其补偿交易恢复所创建的订单。

Saga模式的优点

Saga模式的一大优势是它支持长期事务。因为每个微服务仅关注其自己的本地原子事务,所以如果微服务运行很长时间,则不会阻止其他微服务。这也允许事务继续等待用户输入。此外,由于所有本地事务都是并行发生的,因此任何对象都没有锁定。

Saga模式的缺点

Saga模式很难调试,特别是涉及许多微服务时。此外,如果系统变得复杂,事件消息可能变得难以维护。Saga模式的另一个缺点是它没有读取隔离。例如,客户可以看到正在创建的订单,但在下一秒,订单将因补偿交易而被删除。

添加流程管理器

为了解决Saga模式的复杂性问题,将流程管理器添加为协调器是很正常的。流程管理器负责监听事件和触发端点。

结论

Saga模式是解决基于微服务的体系结构的分布式事务问题的优选方式。但是,它还引入了一组新问题,例如如何以原子方式更新数据库并发出事件。采用Saga模式需要改变开发和测试的思维方式。对于不熟悉这种模式的团队来说,这可能是一个挑战。有许多变体可以简化其实现。因此,选择适当的方式为项目实施它是很重要的。

[该贴被banq于2018-10-04 18:42修改过]


以上所述就是小编给大家介绍的《微服务分布式事务》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Charlotte's Web

Charlotte's Web

E. B. White / Puffin Classics / 2010-6-3 / GBP 6.99

This is the story of a little girl named Fern who loved a little pig named Wilbur and of Wilbur's dear friend, Charlotte A. Cavatica, a beautiful large grey spider. With the unlikely help of Templeton......一起来看看 《Charlotte's Web》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

SHA 加密
SHA 加密

SHA 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具