柔性分布式事务

柔性分布式事务是相对刚性分布式事务、是对强一致性的妥协(也称补偿性事务),从而降低对数据库资源的锁定时间,提升系统的性能。柔性分布式事务适合于长事务、高并发,强调最终一致性的场合。常用的实现柔性分布式事务的方式有:TCC模型、Saga模型、基于消息队列的异步模型。

1、TCC(Try-Confirm-Cancel)模型

img

TCC是一个两阶段提交(2PC)的实现,每一个业务都需要实现Try-Confirm-Cancel三个接口

Try:准备阶段,是尝试执行业务,完成所有业务执行前的检查;

​ 协调者调用所有的每个微服务提供的 try 接口,将整个全局事务涉及到的资源锁定住,若锁定成功 try 接口向协调者返回 yes。

Confirm:提交阶段,是真正执行业务,提交事务,释放资源;

​ 若所有的服务的 try 接口在阶段一都返回 yes,则进入提交阶段,协调者调用所有服务的 confirm 接口,各个服务进行事务提交。

Cancel:取消阶段,业务失败的时候回滚业务操作,释放资源。

​ 如果有任何一个服务的 try 接口在阶段一返回 no 或者超时,则协调者调用所有服务的 cancel 接口。

使用的电商微服务模型如下图所示,在这个模型中,shopping-service 是事务协调者,repo-service 和 order-service 是事务参与者。

img

TCC模型的实现是分为2步操作完成一次事务操作,达到最终事务的一致性。

TCC 的流程如下图所示:

img

这里有个关键问题,既然 TCC 是一种服务层面上的 2PC,它是如何解决 2PC 无法应对宕机问题的缺陷的呢?

答案是不断重试。由于 try 操作锁住了全局事务涉及的所有资源,保证了业务操作的所有前置条件得到满足,因此无论是 confirm 阶段失败还是 cancel 阶段失败都能通过不断重试直至 confirm 或 cancel 成功(所谓成功就是所有的服务都对 confirm 或者 cancel 返回了 ACK)。

这里还有个关键问题,在不断重试 confirm 和 cancel 的过程中(考虑到网络二将军问题的存在)有可能重复进行了 confirm 或 cancel,因此还要再保证 confirm 和 cancel 操作具有幂等性,也就是整个全局事务中,每个参与者只进行一次 confirm 或者 cancel。

实现 confirm 和 cancel 操作的幂等性,有很多解决方案,例如每个参与者可以维护一个去重表(可以利用数据库表实现也可以使用内存型 KV 组件实现),记录每个全局事务(以全局事务标记 XID 区分)是否进行过 confirm 或 cancel 操作,若已经进行过,则不再重复执行。

TCC 由支付宝团队提出,被广泛应用于金融系统中。我们用银行账户余额购买基金时,会注意到银行账户中用于购买基金的那部分余额首先会被冻结,由此我们可以猜想,也就是进入了 TCC 的第一阶段。

优点:

性能提升,具体业务来实现控制资源锁的粒度大小

数据最终一致性,基于confirm和cancel的幂等性,确保事务最终完成是提交还是取消的最终一致性

可靠性,解决了XA协议的协调者单点故障问题,有主业务发起并控制整个业务活动,业务活动管理器也变为多点,引入集群

缺点:

TCC的try,confirm和cancel操作功能要按具体业务来实现,业务耦合度较高,提高了开发成本

2、Saga模式

起源于1987年Hector Garcia-Molina和Kenneth Salem发表的论文《Sagas》,主要思想是把一个分布式事务拆分为多个本地事务,每一个本地事务都有相应的正常执行方法和异常补偿方法,当任意一个本地事务出错时,都可以通过调用相应的异常补偿方法恢复之前的事务或是继续执行未完成的事务,保证事务的最终一致性。

82b397ff72c2fd6d0db81e25b5fc1e86.png

它是一种基于失败的设计,如上图可以看到,每个活动或者子事务流程,一般都会有对应的补偿服务。如果分布式事务发生异常的话,在 Saga 模式中,就要进行所谓的“恢复”,恢复有两种方式,逆向补偿和正向重试。

比如上面的分布式事务执行到 T3 失败,逆向补偿将会依次执行对应的 C3、C2、C1 操作,取消事务活动的“影响”。

那正向补偿,它是一往无前的,T3 失败了,会进行不断的重试,然后继续按照流程执行 T4、T5 等。

Saga的实现方式

有多种,流行的有基于事件的方式和基于命令的方式。

基于事件:(Event Choreography)

没有协调中心,整个模式的工作方式就像舞蹈一样,每个舞蹈者按照预先编排的动作和走位各自表演,最终形成舞蹈。处于当前Saga下的各个服务,会产生某类事件,或者监听其他服务产生的时间并决定是否针对要监听的时间做响应。

优点:

  • 各参与方相互无直接沟通,完全解耦
  • 适合整个分布式事务只有2-4个步骤。

缺点:

  • 如果业务方较多,容易失控。

  • 各个业务参与方可随意监控对方消息,最后可能没人知道到底那个系统在监听哪些消息,甚至坏环监听(两个业务相互监听对方产生的事件)

基于命令:(Order Orchestrator)

这种形式就像乐队,由一个指挥家(协调中心)来协调大家的工作。协调中心来告诉Saga的参与者应该执行哪一部分本地事务。

优点:

  • 服务之间关系简单,避免服务间循环依赖
  • 事务交由协调中心管理,协调中心对整个业务非常清晰
  • 程序开发简单,只需要执行命令/回复(其实回复消息也是一种事件消息),降低参与者的复杂性
  • 易维护扩展,在添加新步骤时,事务复杂性保持线性,回滚更容易管理,更容易实施和测试

缺点:

  • 中央协调器处理逻辑容易变得庞大复杂,导致难以维护。
  • 存在协调器单点故障风险。
2.2 seeta-saga状态机模式

Seata是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。

Seata将为用户提供了AT、TCC、SAGA和XA事务模式,为用户打造一站式的分布式解决方案。

img

1.1 Seata的三大角色

在 Seata 的架构中,一共有三个角色:

TC (Transaction Coordinator) - 事务协调者

维护全局和分支事务的状态,驱动全局事务提交或回滚。

TM (Transaction Manager) - 事务管理器

定义全局事务的范围:开始全局事务、提交或回滚全局事务。

RM (Resource Manager) - 资源管理器

管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

其中,TC 为单独部署的 Server 服务端,TM 和 RM 为嵌入到应用中的 Client 客户端。

Seata Saga的实现方式:

Seata Saga 的实现方式是编排式,是基于状态机引擎实现的。状态机执行的最小单位是节点:节点可以表示一个服务调用,对应 Saga 事务就是子事务活动或流程,也可以配置其补偿节点,通过链路的串联,编排出一个状态机调用流程。在 Seata 里,调用流程目前使用 JSON 描述,由状态机引擎驱动执行,当异常的时候,我们也可以选择补偿策略,由 Seata 协调者端触发事务补偿。

有没有感觉像是服务编排,区别于服务编排,Seata Saga 状态机是 Saga+服务编排,支持补偿服务,保证最终一致性。

我们来看看一个简单的状态机流程定义:

img

上方是一个 Name 为 reduceIncentoryAndBalance 的状态机描述,里面定了 ServiceTask 类型的服务调用节点以及对应的补偿节点 CompensateReduceInventory。

看看几个基本的属性:

Type:节点类型,Seata Saga 支持多种类型的节点。例如 ServiceTask 是服务调用节点

ServiceName/ServiceMethod:标识 ServiceTask 服务及对应方法

Input/Output:定义输入输出参数,输入输出参数取值目前使用的是 SPEL 表达式

Retry:控制重试流程

Catch/Next:用于流程控制、衔接,串联整个状态机流程

Seata -saga工作流程图:

更多类型和语法可以参考 Seata 官方文档[1],可以看到状态机 JSON 声明还是有些难度的,为了简化状态机 JSON 的编写,我们也提供了可视化的编排界面[2],如下所示,编排了一个较为复杂的流程。

41e12d3fa3e144a3358abeebd866e6f9.png

Reduce Inventory 进行扣减库存

Reduce Balance 进行扣减余额

Compensation Trigger 触发补偿机制

Compen Inventory 进行补偿库存

Compen Balance 进行补偿余额

优点:

  • Saga模式非常适合用来处理时间跨度比较长的分布式事务问题。

  • 对于分布式事务参与方的完成时效性没有要求。

  • Saga模式可以在不同的阶段进行补偿操作,从而保证了数据的最终一致性。

  • Saga模式可以通过异步消息来实现,从而提高了系统的可扩展性。

缺点:

  • Saga模式需要开发人员自己实现补偿操作,这增加了开发难度。
  • Saga模式需要开发人员自己实现事务状态机,这增加了开发难度。
  • Saga模式可能会导致事务执行时间过长,从而影响系统的性能。
2.2. Seata-AT模式

Seata 的 AT 模式建立在关系型数据库的本地事务特性的基础之上,通过数据源代理类拦截并解析数据库执行的 SQL,记录自定义的回滚日志,如需回滚,则重放这些自定义的回滚日志即可。

AT 模式虽然是根据 XA 事务模型(2PC)演进而来的,但是 AT 打破了 XA 协议的阻塞性制约,在一致性和性能上取得了平衡。

AT 模式是基于 XA 事务模型演进而来的,它的整体机制也是一个改进版本的两阶段提交协议。AT 模式的两个基本阶段是:

1)第一阶段:首先获取本地锁,执行本地事务,业务数据操作和记录回滚日志在同一个本地事务中提交,最后释放本地锁;

2)第二阶段:如需全局提交,异步删除回滚日志即可,这个过程很快就能完成。如需要回滚,则通过第一阶段的回滚日志进行反向补偿。

Seata in AT mode 的工作原理使用的电商微服务模型如下图所示:

img

在上图中,协调者 shopping-service 先调用参与者 repo-service 扣减库存,后调用参与者 order-service 生成订单。这个业务流使用 Seata in XA mode 后的全局事务流程如下图所示:

img

上图描述的全局事务执行流程为:

1)shopping-service 向 Seata 注册全局事务,并产生一个全局事务标识 XID

2)将 repo-service.repo_db、order-service.order_db 的本地事务执行到待提交阶段,事务内容包含对 repo-service.repo_db、order-service.order_db 进行的查询操作以及写每个库的 undo_log 记录

3)repo-service.repo_db、order-service.order_db 向 Seata 注册分支事务,并将其纳入该 XID 对应的全局事务范围

4)提交 repo-service.repo_db、order-service.order_db 的本地事务

5)repo-service.repo_db、order-service.order_db 向 Seata 汇报分支事务的提交状态

6)Seata 汇总所有的 DB 的分支事务的提交状态,决定全局事务是该提交还是回滚

7)Seata 通知 repo-service.repo_db、order-service.order_db 提交/回滚本地事务,若需要回滚,采取的是补偿式方法

其中 1)2)3)4)5)属于第一阶段,6)7)属于第二阶段。

2.2. Seata in AT mode 工作流程详述

在上面的电商业务场景中,购物服务调用库存服务扣减库存,调用订单服务创建订单,显然这两个调用过程要放在一个事务里面。即:

start global_trx

 call 库存服务的扣减库存接口

 call 订单服务的创建订单接口

commit global_trx

在库存服务的数据库中,存在如下的库存表 t_repo:

idproduction_codenamecountprice
1000120001xx 键盘98200.0
1000220002yy 鼠标199100.0

在订单服务的数据库中,存在如下的订单表 t_order:

idorder_codeuser_idproduction_codecountprice
30001202010250000140001200021100.0
30002202010250000140001200012400.0

现在,id 为 40002 的用户要购买一只商品代码为 20002 的鼠标,整个分布式事务的内容为:

1)在库存服务的库存表中将记录

idproduction_codenamecountprice
1000220002yy 鼠标199100.0

修改为

idproduction_codenamecountprice
1000220002yy 鼠标198100.0

2)在订单服务的订单表中添加一条记录

idorder_codeuser_idproduction_codecountprice
30003202010250000240002200021100.0

以上操作,在 AT 模式的第一阶段的流程图如下:

img

从 AT 模式第一阶段的流程来看,分支的本地事务在第一阶段提交完成之后,就会释放掉本地事务锁定的本地记录。这是 AT 模式和 XA 最大的不同点,在 XA 事务的两阶段提交中,被锁定的记录直到第二阶段结束才会被释放。所以 AT 模式减少了锁记录的时间,从而提高了分布式事务的处理效率。AT 模式之所以能够实现第一阶段完成就释放被锁定的记录,是因为 Seata 在每个服务的数据库中维护了一张 undo_log 表,其中记录了对 t_order / t_repo 进行操作前后记录的镜像数据,即便第二阶段发生异常,只需回放每个服务的 undo_log 中的相应记录即可实现全局回滚。

undo_log 的表结构:

idbranch_idxidcontextrollback_infolog_statuslog_createdlog_modified
……分支事务 ID全局事务 ID……分支事务操作的记录在事务前后的记录镜像,即 beforeImage 和 afterImage………………

第一阶段结束之后,Seata 会接收到所有分支事务的提交状态,然后决定是提交全局事务还是回滚全局事务。

1)若所有分支事务本地提交均成功,则 Seata 决定全局提交。Seata 将分支提交的消息发送给各个分支事务,各个分支事务收到分支提交消息后,会将消息放入一个缓冲队列,然后直接向 Seata 返回提交成功。之后,每个本地事务会慢慢处理分支提交消息,处理的方式为:删除相应分支事务的 undo_log 记录。之所以只需删除分支事务的 undo_log 记录,而不需要再做其他提交操作,是因为提交操作已经在第一阶段完成了(这也是 AT 和 XA 不同的地方)。这个过程如下图所示:

img

分支事务之所以能够直接返回成功给 Seata,是因为真正关键的提交操作在第一阶段已经完成了,清除 undo_log 日志只是收尾工作,即便清除失败了,也对整个分布式事务不产生实质影响。

2)若任一分支事务本地提交失败,则 Seata 决定全局回滚,将分支事务回滚消息发送给各个分支事务,由于在第一阶段各个服务的数据库上记录了 undo_log 记录,分支事务回滚操作只需根据 undo_log 记录进行补偿即可。全局事务的回滚流程如下图所示:

img

这里对图中的 2、3 步做进一步的说明:

1)由于上文给出了 undo_log 的表结构,所以可以通过 xid 和 branch_id 来找到当前分支事务的所有 undo_log 记录;

2)拿到当前分支事务的 undo_log 记录之后,首先要做数据校验,如果 afterImage 中的记录与当前的表记录不一致,说明从第一阶段完成到此刻期间,有别的事务修改了这些记录,这会导致分支事务无法回滚,向 Seata 反馈回滚失败;如果 afterImage 中的记录与当前的表记录一致,说明从第一阶段完成到此刻期间,没有别的事务修改这些记录,分支事务可回滚,进而根据 beforeImage 和 afterImage 计算出补偿 SQL,执行补偿 SQL 进行回滚,然后删除相应 undo_log,向 Seata 反馈回滚成功。

事务具有 ACID 特性,全局事务解决方案也在尽量实现这四个特性。以上关于 Seata in AT mode 的描述很显然体现出了 AT 的原子性、一致性和持久性。下面着重描述一下 AT 如何保证多个全局事务的隔离性的。

在 AT 中,当多个全局事务操作同一张表时,通过全局锁来保证事务的隔离性。下面描述一下全局锁在读隔离和写隔离两个场景中的作用原理:

1)写隔离(若有全局事务在改/写/删记录,另一个全局事务对同一记录进行的改/写/删要被隔离起来,即写写互斥):写隔离是为了在多个全局事务对同一张表的同一个字段进行更新操作时,避免一个全局事务在没有被提交成功之前所涉及的数据被其他全局事务修改。写隔离的基本原理是:在第一阶段本地事务(开启本地事务的时候,本地事务会对涉及到的记录加本地锁)提交之前,确保拿到全局锁。如果拿不到全局锁,就不能提交本地事务,并且不断尝试获取全局锁,直至超出重试次数,放弃获取全局锁,回滚本地事务,释放本地事务对记录加的本地锁。

假设有两个全局事务 gtrx_1 和 gtrx_2 在并发操作库存服务,意图扣减如下记录的库存数量:

AT 实现写隔离过程的时序图如下:

img

图中,1、2、3、4 属于第一阶段,5 属于第二阶段。

在上图中 gtrx_1 和 gtrx_2 均成功提交,如果 gtrx_1 在第二阶段执行回滚操作,那么 gtrx_1 需要重新发起本地事务获取本地锁,然后根据 undo_log 对这个 id=10002 的记录进行补偿式回滚。此时 gtrx_2 仍在等待全局锁,且持有这个 id=10002 的记录的本地锁,因此 gtrx_1 会回滚失败(gtrx_1 回滚需要同时持有全局锁和对 id=10002 的记录加的本地锁),回滚失败的 gtrx_1 会一直重试回滚。直到旁边的 gtrx_2 获取全局锁的尝试次数超过阈值,gtrx_2 会放弃获取全局锁,发起本地回滚,本地回滚结束后,自然会释放掉对这个 id=10002 的记录加的本地锁。此时,gtrx_1 终于可以成功对这个 id=10002 的记录加上了本地锁,同时拿到了本地锁和全局锁的 gtrx_1 就可以成功回滚了。整个过程,全局锁始终在 gtrx_1 手中,并不会发生脏写的问题。整个过程的流程图如下所示:

img

2)读隔离(若有全局事务在改/写/删记录,另一个全局事务对同一记录的读取要被隔离起来,即读写互斥):在数据库本地事务的隔离级别为读已提交、可重复读、串行化时(读未提交不起什么隔离作用,一般不使用),Seata AT 全局事务模型产生的隔离级别是读未提交,也就是说一个全局事务会看到另一个全局事务未全局提交的数据,产生脏读,从前文的第一阶段和第二阶段的流程图中也可以看出这一点。这在最终一致性的分布式事务模型中是可以接受的。

如果要求 AT 模型一定要实现读已提交的事务隔离级别,可以利用 Seata 的 SelectForUpdateExecutor 执行器对 SELECT FOR UPDATE 语句进行代理。SELECT FOR UPDATE 语句在执行时会申请全局锁,如果全局锁已经被其他全局事务占有,则回滚 SELECT FOR UPDATE 语句的执行,释放本地锁,并且重试 SELECT FOR UPDATE 语句。在这个过程中,查询请求会被阻塞,直到拿到全局锁(也就是要读取的记录被其他全局事务提交),读到已被全局事务提交的数据才返回。这个过程如下图所示:

img

3、基于消息队列的异步模型

无论是 2PC & 3PC 还是 TCC、事务状态表,基本都遵守 XA 协议的思想,即这些方案本质上都是事务协调者协调各个事务参与者的本地事务的进度,使所有本地事务共同提交或回滚,最终达成一种全局的 ACID 特性。在协调的过程中,协调者需要收集各个本地事务的当前状态,并根据这些状态发出下一阶段的操作指令。

但是这些全局事务方案由于操作繁琐、时间跨度大,或者在全局事务期间会排他地锁住相关资源,使得整个分布式系统的全局事务的并发度不会太高。这很难满足电商等高并发场景对事务吞吐量的要求,因此互联网服务提供商探索出了很多与 XA 协议背道而驰的分布式事务解决方案。

其中利用消息中间件实现的最终一致性全局事务就是一个经典方案。

为了表现出这种方案的精髓,我将使用如下的电商系统微服务结构来进行描述:

img

在这个模型中,用户不再是请求整合后的 shopping-service 进行下单,而是直接请求 order-service 下单,order-service 一方面添加订单记录,另一方面会调用 repo-service 扣减库存。

这种基于消息中间件的最终一致性事务方案实现方式:

如下所示:

img

完整业务流程图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当用户下单操作业务开始,订单服务先插入订单表,并记录事件表,定时任务会读取未发送的事件(0未发送,1已发送)发到消息队列并将事件状态改为1.

库存服务监听程序会消费消息队列中的消息,并根据事件记录事件表,并返回消息队列ACK确认。库存服务中同样有一个定时任务读取事件,并将未处理(0未处理,1已处理)的做响应的扣减库存操作。

上图所示的方案,利用消息中间件如 rabbitMQ 来实现分布式下单及库存扣减过程的最终一致性。对这幅图做以下说明:

1)order-service 中,

在 t_order 表添加订单记录 &&

在 t_local_msg 添加对应的扣减库存消息

这两个过程要在一个事务中完成,保证过程的原子性。同样,repo-service 中,

检查本次扣库存操作是否已经执行过 &&

执行扣减库存如果本次扣减操作没有执行过 &&

写判重表 &&

向 MQ sever 反馈消息消费完成 ACK

这四个过程也要在一个事务中完成,保证过程的原子性。

2)order-service 中有一个后台程序,源源不断地把消息表中的消息传送给消息中间件,成功后则删除消息表中对应的消息。如果失败了,也会不断尝试重传。由于存在网络 2 将军问题,即当 order-service 发送给消息中间件的消息网络超时时,这时候消息中间件可能收到了消息但响应 ACK 失败,也可能没收到,order-service 会再次发送该消息,直至消息中间件响应 ACK 成功,这样可能发生消息的重复发送,不过没关系,只要保证消息不丢失,不乱序就行,后面 repo-service 会做去重处理。

3)消息中间件向 repo-service 推送 repo_deduction_msg,repo-service 成功处理完成后会向中间件响应 ACK,消息中间件收到这个 ACK 才认为 repo-service 成功处理了这条消息,否则会重复推送该消息。但是有这样的情形:repo-service 成功处理了消息,向中间件发送的 ACK 在网络传输中由于网络故障丢失了,导致中间件没有收到 ACK 重新推送了该消息。这也要靠 repo-service 的消息去重特性来避免消息重复消费。

4)在 2)和 3)中提到了两种导致 repo-service 重复收到消息的原因,一是生产者重复生产,二是中间件重传。为了实现业务的幂等性,repo-service 中维护了一张判重表,这张表中记录了被成功处理的消息的 id。repo-service 每次接收到新的消息都先判断消息是否被成功处理过,若是的话不再重复处理。

通过这种设计,实现了消息在发送方不丢失,消息在接收方不被重复消费**,联合起来就是消息不漏不重**,严格实现了 order-service 和 repo-service 的两个数据库中数据的最终一致性

优点:

基于消息中间件的最终一致性全局事务方案是互联网公司在高并发场景中探索出的一种创新型应用模式,利用 MQ 实现微服务之间的异步调用、解耦合和流量削峰,支持全局事务的高并发,并保证分布式数据记录的最终一致性。降低用户的响应时间,提高系统的吞吐量。

缺点:

系统不能做到强一致,会有短暂不一致。

归纳总结:

XA 协议是 X/Open 提出的分布式事务处理标准。文中提到的 2PC、3PC、TCC、本地事务表、Seata in AT mode,无论哪一种,本质都是事务协调者协调各个事务参与者的本地事务的进度,使使所有本地事务共同提交或回滚,最终达成一种全局的 ACID 特性。在协调的过程中,协调者需要收集各个本地事务的当前状态,并根据这些状态发出下一阶段的操作指令。这个思想就是 XA 协议的要义,我们可以说这些事务模型遵守或大致遵守了 XA 协议。

基于消息中间件的最终一致性事务方案是互联网公司在高并发场景中探索出的一种创新型应用模式,利用 MQ 实现微服务之间的异步调用、解耦合和流量削峰,保证分布式数据记录的最终一致性。它显然不遵守 XA 协议。

对于某项技术,可能存在业界标准或协议,但实践者针对具体应用场景的需求或者出于简便的考虑,给出与标准不完全相符的实现,甚至完全不相符的实现,这在工程领域是一种常见的现象。TCC 方案如此、基于消息中间件的最终一致性事务方案如此、Seata in AT mode 模式也如此。而新的标准往往就在这些创新中产生。

  • 31
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
解刚性/柔性分布式事务是指在分布式系统中处理事务时的两种不同方式。 1. 刚性分布式事务: 刚性分布式事务要求所有参与者在事务执行期间保持一致,并且要求事务在全部参与者上具有原子性、一致性、隔离性和持久性(ACID)特性。在刚性分布式事务中,通常使用两阶段提交(Two-Phase Commit,2PC)协议来实现事务的提交和回滚。2PC协议通过协调者和参与者之间的消息交换,确保所有参与者都同意提交或回滚事务。尽管刚性分布式事务保证了数据的一致性,但由于需要等待全部参与者确认,造成了一定的性能开销,并且在网络故障等情况下可能导致事务的阻塞或中断。 2. 柔性分布式事务柔性分布式事务是一种更为宽松的事务处理方式,主要通过补偿机制来维护数据的最终一致性。在柔性分布式事务中,每个参与者都可以独立地进行自己的操作,并且可以预计到可能存在部分操作失败的情况。当某个操作失败时,通过执行一系列补偿操作来保证数据的一致性。柔性分布式事务通常使用补偿事务(Compensating Transaction)或者事务日志(Transaction Log)来记录操作和补偿操作,并且可以通过重试等机制来处理失败的操作。相比于刚性分布式事务柔性分布式事务更加灵活,能够提供更好的可扩展性和容错性,但在一些特定场景下可能需要额外的开发和设计工作来处理补偿逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

默海情深以往

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值