当前位置: 首页 > 图灵资讯 > java面试题> 分布式事务有哪些常见的实现方案?-Saga事务

分布式事务有哪些常见的实现方案?-Saga事务

来源:图灵教育
时间:2024-04-12 13:37:31
 

Saga事务:

1、什么是Saga事务:

Saga 事务核心思想是将长事务拆分为多个本地短事务并依次正常提交,如果所有短事务均执行成功,那么分布式事务提交;如果出现某个参与者执行本地事务失败,则由 Saga 事务协调器协调根据相反顺序调用补偿操作,回滚已提交的参与者,使分布式事务回到最初始的状态。Saga 事务基本协议如下:

  • (1)每个 Saga 事务由一系列幂等的有序子事务(sub-transaction) Ti 组成。
  • (2)每个 Ti 都有对应的幂等补偿动作 Ci,补偿动作用于撤销 Ti 造成的结果。

与TCC事务补偿机制相比,TCC有一个预留(Try)动作,相当于先报存一个草稿,然后才提交;Saga事务没有预留动作,直接提交。

2、Saga的恢复策略:

对于事务异常,Saga提供了两种恢复策略,分别如下:

(1)向后恢复(backward recovery):

当执行事务失败时,补偿所有已完成的事务,是“一退到底”的方式,这种做法的效果是撤销掉之前所有成功的子事务,使得整个 Saga 的执行结果撤销。如下图:

从上图可知事务执行到了支付事务T3,但是失败了,因此事务回滚需要从C3,C2,C1依次进行回滚补偿,对应的执行顺序为:T1,T2,T3,C3,C2,C1。

(2)向前恢复(forward recovery):

对于执行不通过的事务,会尝试重试事务,这里有一个假设就是每个子事务最终都会成功,这种方式适用于必须要成功的场景,事务失败了重试,不需要补偿。流程如下图:

3、Saga事务的实现方式:

Saga事务有两种不同的实现方式,分别如下:

  • 命令协调(Order Orchestrator)
  • 事件编排(Event Choreographyo)

(1)命令协调:

中央协调器(Orchestrator,简称 OSO)以命令/回复的方式与每项服务进行通信,全权负责告诉每个参与者该做什么以及什么时候该做什么。整体流程如下图:

  • ① 事务发起方的主业务逻辑请求 OSO 服务开启订单事务
  • ② OSO 向库存服务请求扣减库存,库存服务回复处理结果。
  • ③ OSO 向订单服务请求创建订单,订单服务回复创建结果。
  • ④ OSO 向支付服务请求支付,支付服务回复处理结果。
  • ⑤ 主业务逻辑接收并处理 OSO 事务处理结果回复。

中央协调器 OSO 必须事先知道执行整个事务所需的流程,如果有任何失败,它还负责通过向每个参与者发送命令来撤销之前的操作来协调分布式的回滚,基于中央协调器协调一切时,回滚要容易得多,因为协调器默认是执行正向流程,回滚时只要执行反向流程即可。

(2)事件编排:

命令协调方式基于中央协调器实现,所以有单点风险,但是事件编排方式没有中央协调器。事件编排的实现方式中,每个服务产生自己的时间并监听其他服务的事件来决定是否应采取行动。

在事件编排方法中,第一个服务执行一个事务,然后发布一个事件,该事件被一个或多个服务进行监听,这些服务再执行本地事务并发布(或不发布)新的事件。当最后一个服务执行本地事务并且不发布任何事件时,意味着分布式事务结束,或者它发布的事件没有被任何 Saga 参与者听到都意味着事务结束。

  • ① 事务发起方的主业务逻辑发布开始订单事件。
  • ② 库存服务监听开始订单事件,扣减库存,并发布库存已扣减事件。
  • ③ 订单服务监听库存已扣减事件,创建订单,并发布订单已创建事件。
  • ④ 支付服务监听订单已创建事件,进行支付,并发布订单已支付事件。
  • ⑤ 主业务逻辑监听订单已支付事件并处理。

如果事务涉及 2 至 4 个步骤,则非常合适使用事件编排方式,它是实现 Saga 模式的自然方式,它很简单,容易理解,不需要太多的代码来构建。

4、Saga事务的优缺点:

(1)命令协调设计的优缺点:

① 优点:

  • 服务之间关系简单,避免服务间循环依赖,因为 Saga 协调器会调用 Saga 参与者,但参与者不会调用协调器。
  • 程序开发简单,只需要执行命令/回复(其实回复消息也是一种事件消息),降低参与者的复杂性。
  • 易维护扩展,在添加新步骤时,事务复杂性保持线性,回滚更容易管理,更容易实施和测试。

② 缺点:

  • 中央协调器处理逻辑容易变得庞大复杂,导致难以维护。
  • 存在协调器单点故障风险。

(2)事件编排设计的优缺点:

① 优点:

  • 避免中央协调器单点故障风险。
  • 当涉及的步骤较少服务开发简单,容易实现。

② 缺点:

  • 服务之间存在循环依赖的风险。
  • 当涉及的步骤较多,服务间关系混乱,难以追踪调测。

由于 Saga 模型没有 Prepare 阶段,因此事务间不能保证隔离性。当多个 Saga 事务操作同一资源时,就会产生更新丢失、脏数据读取等问题,这时需要在业务层控制并发,例如:在应用层面加锁,或者应用层面预先冻结资源。