微服务-分布式事务之saga模式

半城伤御伤魂 提交于 2020-04-27 17:23:15
  • Saga相关概念

    你已经使用 database ber service 模式,每个service拥有自己的database。一些业务事务会跨越多个service,所以你需要来确保data consistency。应用程序不能简单的使用本地的ACID事务。saga事务模型又被叫做长时间运行的事务(long running transaction),一个长活事务可被分解成可以交错运行的子事务集合。其中每个子事务都是一个保证数据库一致性的真实事务。

   对于分布式事务2PC(两阶段提交)不是一个好的选择,把跨越多个service的每一个单独的事务实现成saga模式。一个saga是由local transaction组成的序列。每个local transaction更新本地数据库,然后发布一个message 或者event来触发下一个事务。如果有一个本地事务失败了,saga就会执行一系列的补偿事务来回滚之前的事务所做的修改。

  • 举例

    如:如电商下单,需要冻结商品库存,然后扣取用户的余额,最终完成订单。库存不足或账户余额不足都会导致下单失败,这里订单、库存、支付都是不同的模块service,都有自己的database

  1. 2PC的实现方式

   2PC在JTA规范中实现如下

JTA控制器统一向3个服务发起prepare请求,如果3个请求都已确认,那3个服务都同时发起commit请求,再整个commit过程中所有涉及到的资源都是处理锁定状态,直到事务提交成功或超时,这样对系统资源消耗巨大的。

2.BASE事务实现方式

 BASE事务采用多段本地事务提交,并大事务拆分成了5个local Transaction(T1-T5)本地事务,并为这些事务做了冲正操作

BASE

T1-订单服务先完成生成订单,订单状态为opened.

T2-库存服务完成锁定库存

T3-订单服务把订单状态更新成Prepared状态

T4-支付服务完成扣款

T5-订单服务把状态更新成commited状态

其中每一步完成都会提交事务,这里的订单多出了两个中间状态prepared和opened,最后才到commited,对比ACID直接一步到了commited,BASE冗长了很多。这样的好处时,第一步只锁定本地资源,对其它服务没有影响,缺点点要自己处理每一步失败的情况,和ACID相比,BASE不能轻易回滾,只能通过补偿(Compensation)操作来达到最终一致性,比如在T4阶段发生交易失败,那么就要执行前3步的冲正操作(C3、C2、C1)
C3-将订单状态改成opend

C2-将库存解锁

C1-将订单置为废弃状态Canelled

  • SAGA实现方式

我们有两种方式来处理处理业务流程和失败补偿

1.让每个服务给后续步骤发送消息

2.通过一个统一的执行协调器来完成

SEC

我们倾向于用统一的执行协调器来做,从严格意义上来说,sage是不包含业务逻辑的,Saga更倾向于“Process”而不是“Logic”

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!