分布式事务 以你之姓@ 2024-03-17 23:38 9阅读 0赞 ## 本地事务 ## 同一个jvm进程调用一个关系型数据库 ## 分布式事务 ## ### 微服务 ### * 微服务 * 不同的微服务调用不同的数据库 ![image.png][] * 不同的微服务调用同一个数据库 ![image.png][image.png 1] ### 多数据源 ### * 多数据源 * 一个jvm进程调用多个数据库 ![image.png][image.png 2] ## CAP理论 ## ### CAP ### #### 一致性 #### * **一致性(Consistency)** : 所有节点访问同一份最新的数据副本 > 对多个数据库加锁 #### 可用性 #### * **可用性(Availability)**: 非故障的节点在合理的时间内返回合理的响应(不是错误或者超时的响应)。 > 对于正常的节点,加锁时间不要过长 #### 分区容错性 #### * **分区容错性(Partition Tolerance)** : 分布式系统出现网络分区的时候,仍然能够对外提供服务。 **什么是网络分区?** 分布式系统中,多个节点之前的网络本来是连通的,但是因为某些故障(比如部分节点网络出了问题)某些节点之间不连通了,整个网络就分成了几块区域,这就叫 **网络分区**。 ![partition-tolerance][] ### AP / CP ### 分区不可避免,因此P是一定要满足的 CP:如果要保证所有节点数据库一致 ,就要等待网络恢复,那么系统将不可用 AP:如果要系统仍然对外提供服务,那么不同的节点之间,将出现不一致 #### AP #### #### CP #### > * **ZooKeeper 保证的是 CP。** 任何时刻对 ZooKeeper 的读请求都能得到一致性的结果,但是, ZooKeeper 不保证每次请求的可用性比如在 Leader 选举过程中或者半数以上的机器不可用的时候服务就是不可用的。 > * **Eureka 保证的则是 AP。** Eureka 在设计的时候就是优先保证 A (可用性)。在 Eureka 中不存在什么 Leader 节点,每个节点都是一样的、平等的。因此 Eureka 不会像 ZooKeeper 那样出现选举过程中或者半数以上的机器不可用的时候服务就是不可用的情况。 Eureka 保证即使大部分节点挂掉也不会影响正常提供服务,只要有一个节点是可用的就行了。只不过这个节点上的数据可能并不是最新的。 > * **Nacos 不仅支持 CP 也支持 AP。** ## BASE理论 ## ### 基本可用 ### Basically Available 基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性。但是,这绝不等价于系统不可用。 **什么叫允许损失部分可用性呢?** * **响应时间上的损失**: 正常情况下,处理用户请求需要 0.5s 返回结果,但是由于系统出现故障,处理用户请求的时间变为 3 s。 * **系统功能上的损失**:正常情况下,用户可以使用系统的全部功能,但是由于系统访问量突然剧增,系统的部分非核心功能无法使用。 ### 软状态 ### Soft-state 软状态指允许系统中的数据存在中间状态(**CAP 理论中的数据不一致**),并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时。 ### 最终一致性 ### Eventually Consistent 最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。 > 分布式一致性的 3 种级别: > > 1. **强一致性**:系统写入了什么,读出来的就是什么。 > 2. **弱一致性**:不一定可以读取到最新写入的值,也不保证多少时间之后读取到的数据是最新的,只是会尽量保证某个时刻达到数据一致的状态。 > 3. **最终一致性**:弱一致性的升级版,系统会保证在一定时间内达到数据一致的状态。 > > **业界比较推崇是最终一致性级别,但是某些对数据一致要求十分严格的场景比如银行转账还是要保证强一致性。** 那实现最终一致性的具体方式是什么呢? > * **读时修复** : 在读取数据时,检测数据的不一致,进行修复。比如 Cassandra 的 Read Repair 实现,具体来说,在向 Cassandra 系统查询数据的时候,如果检测到不同节点的副本数据不一致,系统就自动修复数据。 > * **写时修复** : 在写入数据,检测数据的不一致时,进行修复。比如 Cassandra 的 Hinted Handoff 实现。具体来说,Cassandra 集群的节点之间远程写数据的时候,如果写失败 就将数据缓存下来,然后定时重传,修复数据的不一致性。 > * **异步修复** : 这个是最常用的方式,通过定时对账检测副本数据的一致性,并修复。 比较推荐 **写时修复**,这种方式对性能消耗比较低 ## 解决方案 ## ![image.png][image.png 3] ### 强一致性 ### #### 2PC-两阶段提交 #### ##### 数据库层面 ##### 为了解决redolog和binlog两份日志之间的逻辑一致问题,InnoDB存储引擎使用两阶段提交方案。原理很简单,将redo log的写入拆成了两个步骤prepare和commit,这就是两阶段提交。 ![请添加图片描述][watermark_type_d3F5LXplbmhlaQ_shadow_50_text_Q1NETiBA5YeG5Zu-54G15aWW5b6X5Li7_size_20_color_FFFFFF_t_70_g_se_x_16] 使用两阶段提交后,写入binlog时发生异常也不会有影响,因为MySQL根据redo log日志恢复数据时,发现redolog还处于prepare阶段,并且没有对应binlog日志,就会回滚该事务。 ![请添加图片描述][watermark_type_d3F5LXplbmhlaQ_shadow_50_text_Q1NETiBA5YeG5Zu-54G15aWW5b6X5Li7_size_20_color_FFFFFF_t_70_g_se_x_16 1] 另一个场景,redo log设置commit阶段发生异常,那会不会回滚事务呢? ![请添加图片描述][watermark_type_d3F5LXplbmhlaQ_shadow_50_text_Q1NETiBA5YeG5Zu-54G15aWW5b6X5Li7_size_20_color_FFFFFF_t_70_g_se_x_16 2] 并不会回滚事务,它会执行上图框住的逻辑,虽然redo log是处于prepare阶段,但是能通过事务id找到对应的binlog日志,所以MySQL认为是完整的,就会提交事务恢复数据。 ##### XA方案 ##### 2PC的传统方案是在数据库层面实现的,如Oracle、MySQL都支持2PC协议,为了统一标准减少行业内不必要的对 接成本,需要制定标准化的处理模型及接口标准,国际开放标准组织Open Group定义了分布式事务处理模型 DTP(Distributed Transaction Processing Reference Model)。 为了让大家更明确XA方案的内容程,下面新用户注册送积分为例来说明: ![image.png][image.png 4] 执行流程如下: 1、应用程序(AP)持有用户库和积分库两个数据源。 2、应用程序(AP)通过TM通知用户库RM新增用户,同时通知积分库RM为该用户新增积分,RM此时并未提交事 务,此时用户和积分资源锁定。 3、TM收到执行回复,只要有一方失败则分别向其他RM发起回滚事务,回滚完毕,资源锁释放。 4、TM收到执行回复,全部成功,此时向所有RM发起提交事务,提交完毕,资源锁释放。 DTP模型定义如下角色: * AP(Application Program):即应用程序,可以理解为使用DTP分布式事务的程序。 * RM(Resource Manager):即资源管理器,可以理解为事务的参与者,一般情况下是指一个数据库实例,通过 资源管理器对该数据库进行控制,资源管理器控制着分支事务。 * TM(Transaction Manager):事务管理器,负责协调和管理事务,事务管理器控制着全局事务,管理事务生命 周期,并协调各个RM。全局事务是指分布式事务处理环境中,需要操作多个数据库共同完成一个工作,这个 工作即是一个全局事务。 DTP模型定义TM和RM之间通讯的接口规范叫XA,简单理解为数据库提供的2PC接口协议,基于数据库的XA 协议来实现2PC又称为XA方案。 以上三个角色之间的交互方式如下: 1)TM向AP提供 应用程序编程接口,AP通过TM提交及回滚事务。 2)TM交易中间件通过XA接口来通知RM数据库事务的开始、结束以及提交、回滚等。 总结: 整个2PC的事务流程涉及到三个角色AP、RM、TM。 * AP指的是使用2PC分布式事务的应用程序; * RM指的是资 源管理器,它控制着分支事务; * TM指的是事务管理器,它控制着整个全局事务。 1)在准备阶段RM执行实际的业务操作,但不提交事务,资源锁定; 2)在提交阶段TM会接受RM在准备阶段的执行回复,只要有任一个RM执行失败,TM会通知所有RM执行回滚操 作,否则,TM将会通知所有RM提交该事务。提交阶段结束资源锁释放。 XA方案的问题: 1、需要本地数据库支持XA协议。 2、资源锁需要等到两个阶段结束才释放,性能较差。 1. 准备阶段(Prepare phase):事务管理器给每个参与者发送Prepare消息,每个数据库参与者在本地执行事 务,并写本地的Undo/Redo日志,此时事务没有提交。 (Undo日志是记录修改前的数据,用于数据库回滚,Redo日志是记录修改后的数据,用于提交事务后写入数 据文件) 2. 提交阶段(commit phase):如果事务管理器收到了参与者的执行失败或者超时消息时,直接给每个参与者 发送回滚(Rollback)消息;否则,发送提交(Commit)消息;参与者根据事务管理器的指令执行提交或者回滚操 作,并释放事务处理过程中使用的锁资源。注意:必须在最后阶段释放锁资源。 下图展示了2PC的两个阶段,分成功和失败两个情况说明: 成功情况: ![image.png][image.png 5] 失败情况: ![image.png][image.png 6] ###### Seata-XA模式 ###### Seata是 阿里巴巴共同开源的分布式事务解决方案。 eata事务管理中有三个重要的角色: * **TC (Transaction Coordinator) -** **事务协调者:** 事务协调器,它是独立的中间件,需要独立部署运行,它维护全局事务的运 行状态,接收TM指令发起全局事务的提交与回滚,负责与RM通信协调各各分支事务的提交或回滚。 * **TM (Transaction Manager) -** **事务管理器:** 事务管理器,TM需要嵌入应用程序中工作,它负责开启一个全局事务,并最终 向TC发起全局提交或全局回滚的指令。 * **RM (Resource Manager) -** **资源管理器:** 控制分支事务,负责分支注册、状态汇报,并接收事务协调器TC的指令,驱动分 支(本地)事务的提交和回滚。 ![image.png][image.png 7] Seata基于上述架构提供了四种不同的分布式事务解决方案: * XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入 * TCC模式:最终一致的分阶段事务模式,有业务侵入 * AT模式:最终一致的分阶段事务模式,无业务侵入,也是Seata的默认模式 * SAGA模式:长事务模式,有业务侵入 Seata对原始的XA模式做了简单的封装和改造,以适应自己的事务模型,基本架构如图: ![image.png][image.png 8] RM一阶段的工作: ① 注册分支事务到TC ② 执行分支业务sql但不提交 ③ 报告执行状态到TC TC二阶段的工作: * TC检测各分支事务执行状态 a.如果都成功,通知所有RM提交事务 b.如果有失败,通知所有RM回滚事务 RM二阶段的工作: * 接收TC指令,提交或回滚事务 实现XA模式 Seata的starter已经完成了XA模式的自动装配,实现非常简单,步骤如下: 1)修改application.yml文件(每个参与事务的微服务),开启XA模式: seata: data-source-proxy-mode: XA 2)给发起全局事务的入口方法添加@GlobalTransactional注解: 本例中是OrderServiceImpl中的create方法. \[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZTddMuJh-1689949027340)(assets/image-20210724174859556.png)\] 3)重启服务并测试 重启order-service,再次测试,发现无论怎样,三个微服务都能成功回滚。 ###### 优缺点 ###### XA模式的优点是什么? * 事务的强一致性,满足ACID原则。 * 常用数据库都支持,实现简单,并且没有代码侵入 XA模式的缺点是什么? * 因为一阶段需要锁定数据库资源,等待二阶段结束才释放,性能较差 * 依赖关系型数据库实现事务 ##### Seat-AT 模式 ##### AT模式同样是分阶段提交的事务模型,不过缺弥补了XA模型中资源锁定周期过长的缺陷。 Seata的AT模型(默认) 基本流程图: \[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7jCZ78Bj-1689949027341)(assets/image-20210724175327511.png)\] 阶段一RM的工作: * 注册分支事务 * 记录undo-log(数据快照) * 执行业务sql并提交 * 报告事务状态 阶段二提交时RM的工作: * 删除undo-log即可 阶段二回滚时RM的工作: * 根据undo-log恢复数据到更新前 ![image.png][image.png 9] ![image.png][image.png 10] 具体的执行流程如下: 1. 用户服务的 TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID。 2. 用户服务的 RM 向 TC 注册 分支事务,该分支事务在用户服务执行新增用户逻辑,并将其纳入 XID 对应全局 事务的管辖。 3. 用户服务执行分支事务,向用户表插入一条记录。 4. 逻辑执行到远程调用积分服务时(XID 在微服务调用链路的上下文中传播)。积分服务的RM 向 TC 注册分支事 务,该分支事务执行增加积分的逻辑,并将其纳入 XID 对应全局事务的管辖。 5. 积分服务执行分支事务,向积分记录表插入一条记录,执行完毕后,返回用户服务。 6. 用户服务分支事务执行完毕。 7. TM 向 TC 发起针对 XID 的全局提交或回滚决议。 8. TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。 简述AT模式与XA模式最大的区别是什么? * XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源。 * XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚。 * XA模式强一致;AT模式最终一致 Seata实现2PC与传统2PC的差别: * 架构层次方面,传统2PC方案的 RM 实际上是在数据库层,RM 本质上就是数据库自身,通过 XA 协议实现,而 Seata的 RM 是以jar包的形式作为中间件层部署在应用程序这一侧的。 * 两阶段提交方面,传统2PC无论第二阶段的决议是commit还是rollback,事务性资源的锁都要保持到Phase2完成 才释放。而Seata的做法是在Phase1 就将本地事务提交,这样就可以省去Phase2持锁的时间,整体提高效率。 ###### 脏写-全局锁 ###### 在多线程并发访问AT模式的分布式事务时,有可能出现脏写问题,如图: ![image.png][image.png 11] 解决思路就是引入了全局锁的概念。在释放DB锁之前,先拿到全局锁。避免同一时刻有另外一个事务来操作当前数据。 ![image.png][image.png 12] xa模式普通select也会被锁 at模式普通select不会被锁 ###### 优缺点 ###### AT模式的优点: * 一阶段完成直接提交事务,释放数据库资源,性能比较好 * 利用全局锁实现读写隔离 * 没有代码侵入,框架自动完成回滚和提交 AT模式的缺点: * 两阶段之间属于软状态,属于最终一致 * 框架的快照功能会影响性能,但比XA模式要好很多 实现AT模式: AT模式中的快照生成、回滚等动作都是由框架自动完成,没有任何代码侵入,因此实现非常简单。 只不过,AT模式需要一个表来记录全局锁、另一张表来记录数据快照undo\_log。 ### 最终一致性 ### #### Seata-TCC 模式 #### TCC模式与AT模式非常相似,每阶段都是独立事务,不同的是TCC通过人工编码来实现数据恢复。需要实现三个方法: * Try:资源的检测和预留; * Confirm:完成资源操作业务;要求 Try 成功 Confirm 一定要能成功。 * Cancel:预留资源释放,可以理解为try的反向操作。 举例,一个扣减用户余额的业务。假设账户A原来余额是100,需要余额扣减30元。 * **阶段一( Try )**:检查余额是否充足,如果充足则冻结金额增加30元,可用余额扣除30 初识余额: ![image.png][image.png 13] 余额充足,可以冻结 ![image.png][image.png 14] 此时,总金额 = 冻结金额 + 可用金额,数量依然是100不变。事务直接提交无需等待其它事务。 * **阶段二(Confirm)**:假如要提交(Confirm),则冻结金额扣减30 确认可以提交,不过之前可用金额已经扣减过了,这里只要清除冻结金额就好了: ![image.png][image.png 15] 此时,总金额 = 冻结金额 + 可用金额 = 0 + 70 = 70元 * **阶段二(Canncel)**:如果要回滚(Cancel),则冻结金额扣减30,可用余额增加30 需要回滚,那么就要释放冻结金额,恢复可用金额: ![image.png][image.png 16] Seata中的TCC模型依然延续之前的事务架构,如图: ![image.png][image.png 17] ##### 优缺点 ##### TCC模式的每个阶段是做什么的? * Try:资源检查和预留 * Confirm:业务执行和提交 * Cancel:预留资源的释放 TCC的优点是什么? * 一阶段完成直接提交事务,释放数据库资源,性能好 * 相比AT模型,无需生成快照,无需使用全局锁,性能最强 * 不依赖数据库事务,而是依赖补偿操作,可以用于非事务型数据库 TCC的缺点是什么? * 有代码侵入,需要人为编写try、Confirm和Cancel接口,太麻烦 * 软状态,事务是最终一致 * 需要考虑Confirm和Cancel的失败情况,做好幂等处理 ##### 空回滚-事务悬挂 ##### 当某分支事务的try阶段**阻塞**时,可能导致全局事务超时而触发二阶段的cancel操作。在未执行try操作时先执行了cancel操作,这时cancel不能做回滚,就是**空回滚**。 > 执行cancel操作时,应当判断try是否已经执行,如果尚未执行,则应该空回滚。 对于已经空回滚的业务,之前被阻塞的try操作恢复,继续执行try,就永远不可能confirm或cancel ,事务一直处于中间状态,这就是**业务悬挂**。 > 执行try操作时,应当判断cancel是否已经执行过了,如果已经执行,应当阻止空回滚后的try操作,避免悬挂 ##### 实现 ##### 解决空回滚和业务悬挂问题,必须要记录当前事务状态,是在try、还是cancel? 1)思路分析 这里我们定义一张表: CREATE TABLE `account_freeze_tbl` ( `xid` varchar(128) NOT NULL, `user_id` varchar(255) DEFAULT NULL COMMENT '用户id', `freeze_money` int(11) unsigned DEFAULT '0' COMMENT '冻结金额', `state` int(1) DEFAULT NULL COMMENT '事务状态,0:try,1:confirm,2:cancel', PRIMARY KEY (`xid`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; 其中: * xid:是全局事务id * freeze\_money:用来记录用户冻结金额 * state:用来记录事务状态 那此时,我们的业务开怎么做呢? * Try业务: * 记录冻结金额和事务状态到account\_freeze表 * 扣减account表可用金额 * Confirm业务 * 根据xid删除account\_freeze表的冻结记录 * Cancel业务 * 修改account\_freeze表,冻结金额为0,state为2 * 修改account表,恢复可用金额 * 如何判断是否空回滚? * cancel业务中,根据xid查询account\_freeze,如果为null则说明try还没做,需要空回滚 * 如何避免业务悬挂? * try业务中,根据xid查询account\_freeze ,如果已经存在则证明Cancel已经执行,拒绝执行try业务 接下来,我们改造account-service,利用TCC实现余额扣减功能。 2)声明TCC接口 TCC的Try、Confirm、Cancel方法都需要在接口中基于注解来声明, 我们在account-service项目中的`cn.itcast.account.service`包中新建一个接口,声明TCC三个接口: package cn.itcast.account.service; import io.seata.rm.tcc.api.BusinessActionContext; import io.seata.rm.tcc.api.BusinessActionContextParameter; import io.seata.rm.tcc.api.LocalTCC; import io.seata.rm.tcc.api.TwoPhaseBusinessAction; @LocalTCC public interface AccountTCCService { @TwoPhaseBusinessAction(name = "deduct", commitMethod = "confirm", rollbackMethod = "cancel") void deduct(@BusinessActionContextParameter(paramName = "userId") String userId, @BusinessActionContextParameter(paramName = "money")int money); boolean confirm(BusinessActionContext ctx); boolean cancel(BusinessActionContext ctx); } 3)编写实现类 在account-service服务中的`cn.itcast.account.service.impl`包下新建一个类,实现TCC业务: package cn.itcast.account.service.impl; import cn.itcast.account.entity.AccountFreeze; import cn.itcast.account.mapper.AccountFreezeMapper; import cn.itcast.account.mapper.AccountMapper; import cn.itcast.account.service.AccountTCCService; import io.seata.core.context.RootContext; import io.seata.rm.tcc.api.BusinessActionContext; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service @Slf4j public class AccountTCCServiceImpl implements AccountTCCService { @Autowired private AccountMapper accountMapper; @Autowired private AccountFreezeMapper freezeMapper; @Override @Transactional public void deduct(String userId, int money) { // 0.获取事务id String xid = RootContext.getXID(); // 1.扣减可用余额 accountMapper.deduct(userId, money); // 2.记录冻结金额,事务状态 AccountFreeze freeze = new AccountFreeze(); freeze.setUserId(userId); freeze.setFreezeMoney(money); freeze.setState(AccountFreeze.State.TRY); freeze.setXid(xid); freezeMapper.insert(freeze); } @Override public boolean confirm(BusinessActionContext ctx) { // 1.获取事务id String xid = ctx.getXid(); // 2.根据id删除冻结记录 int count = freezeMapper.deleteById(xid); return count == 1; } @Override public boolean cancel(BusinessActionContext ctx) { // 0.查询冻结记录 String xid = ctx.getXid(); AccountFreeze freeze = freezeMapper.selectById(xid); // 1.恢复可用余额 accountMapper.refund(freeze.getUserId(), freeze.getFreezeMoney()); // 2.将冻结金额清零,状态改为CANCEL freeze.setFreezeMoney(0); freeze.setState(AccountFreeze.State.CANCEL); int count = freezeMapper.updateById(freeze); return count == 1; } } #### Seata-SAGA模式 #### Saga 模式是 Seata 即将开源的长事务解决方案,将由蚂蚁金服主要贡献。 其理论基础是Hector & Kenneth 在1987年发表的论文[Sagas][]。 Seata官网对于Saga的指南:https://seata.io/zh-cn/docs/user/saga.html 原理 在 Saga 模式下,分布式事务内有多个参与者,每一个参与者都是一个冲正补偿服务,需要用户根据业务场景实现其正向操作和逆向回滚操作。 分布式事务执行过程中,依次执行各参与者的正向操作,如果所有正向操作均执行成功,那么分布式事务提交。如果任何一个正向操作执行失败,那么分布式事务会去退回去执行前面各参与者的逆向回滚操作,回滚已提交的参与者,使分布式事务回到初始状态。 \[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LUSHfloO-1689949027345)(assets/image-20210724184846396.png)\] Saga也分为两个阶段: * 一阶段:直接提交本地事务 * 二阶段:成功则什么都不做;失败则通过编写补偿业务来回滚 ##### 优缺点 ##### 优点: * 事务参与者可以基于事件驱动实现异步调用,吞吐高 * 一阶段直接提交事务,无锁,性能好 * 不用编写TCC中的三个阶段,实现简单 缺点: * 软状态持续时间不确定,时效性差 * 没有锁,没有事务隔离,会有脏写 ##### 四种模式对比 ##### 我们从以下几个方面来对比四种实现: * 一致性:能否保证事务的一致性?强一致还是最终一致? * 隔离性:事务之间的隔离性如何? * 代码侵入:是否需要对业务代码改造? * 性能:有无性能损耗? * 场景:常见的业务场景 如图: #### 可靠消息最终一致性 #### 下面是两个微服务,我们的目标是实现两个数据库数据一致 ![image.png][image.png 18] ![image.png][image.png 19] ##### 消息队列 ##### 本地消息表:保证向消息队列成功发送消息 ![image.png][image.png 20] ![image.png][image.png 21] ##### 任务调度 ##### 本地消息表:记录要同步的数据(可以是id) 任务调度:另外一个线程或者使用xxl-job等第三方服务,定时扫描本地消息表,然后调用其他微服务,同步数据;数据同步完成后,把本地消息表中的记录删掉 ![image.png][image.png 22] ![image.png][image.png 23] #### 最大努力通知 #### [image.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/44efd2b233a6405da9e86c4c78b68ad3.png [image.png 1]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/7bb0d7a439c14e42a15d1f6ecf9e19db.png [image.png 2]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/a9523a8f45a24c4aa366e3a98cbb522e.png [partition-tolerance]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/f581368b3e2d4699b8db78b880036ce7.png [image.png 3]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/130a71c8e7614083b58c41401fd5994f.png [watermark_type_d3F5LXplbmhlaQ_shadow_50_text_Q1NETiBA5YeG5Zu-54G15aWW5b6X5Li7_size_20_color_FFFFFF_t_70_g_se_x_16]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/fbec6b01baea427e86552852e33c5f1f.png [watermark_type_d3F5LXplbmhlaQ_shadow_50_text_Q1NETiBA5YeG5Zu-54G15aWW5b6X5Li7_size_20_color_FFFFFF_t_70_g_se_x_16 1]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/2c58c430db41429a985f7ddfd5d2aaa4.png [watermark_type_d3F5LXplbmhlaQ_shadow_50_text_Q1NETiBA5YeG5Zu-54G15aWW5b6X5Li7_size_20_color_FFFFFF_t_70_g_se_x_16 2]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/f26f5f3a00b748d9b7f0225982dcbadf.png [image.png 4]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/6c44c4d88a964622a2d97a4b8744fb8b.png [image.png 5]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/31f51919b1a94aaf83a1d0e58ea0eeed.png [image.png 6]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/8d142f70063a4b4286be9cc1e26c186b.png [image.png 7]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/8db7a6d0d53b4a52bce64c3be1ec2462.png [image.png 8]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/55687544085d4030b6ae19483ffc4b7b.png [image.png 9]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/4c6fa29c8a174a649c443bae0e0557db.png [image.png 10]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/a841b527715b47f09cc282a98c60ba3b.png [image.png 11]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/fe086f68b65a41189c37d87c92ff6a72.png [image.png 12]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/1c49349e602d4b8ab7e8996962b6da57.png [image.png 13]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/a1929060b89c4e30b0e4fbc1b7f72332.png [image.png 14]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/849d09e940634a288c487382e8e55e05.png [image.png 15]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/9a55923c9c66424aa6966b522c08013e.png [image.png 16]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/a54bb300d0004430b365c04cea81e1f4.png [image.png 17]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/22f58ff755f54282a6c4e1161000c633.png [Sagas]: https://microservices.io/patterns/data/saga.html [image.png 18]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/0a9caa30cbde476a8c1807a83c6a2ce2.png [image.png 19]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/dce447bc179d4b1ab9afc5969f060df0.png [image.png 20]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/95cf3ee233054f0fb5f1eec47aaee2ae.png [image.png 21]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/f835e8a166a4451080b8b84653359aaa.png [image.png 22]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/e6b8ce1ab31a4cc0a0ec0b95f3ea748b.png [image.png 23]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/14/9b4ebdb42667447281b2178197575769.png
相关 【分布式事务】分布式事务Seata 文章目录 前言 什么是分布式事务? (1)数据库分库分表就产生了分布式事务; (2)项目拆分服务化也产生了分布式事务; 一、W 客官°小女子只卖身不卖艺/ 2023年10月09日 13:49/ 0 赞/ 121 阅读
相关 分布式事务(二)分布式事务方案 文章目录 什么是分布式事务 理论部分 CAP BASE 分布式事务方案 什么是分布式事务 首先这是普通事务: ![ 太过爱你忘了你带给我的痛/ 2023年02月28日 01:29/ 0 赞/ 72 阅读
相关 分布式-分布式事务 分布式事务 文章目录 分布式事务 一,本地消息表 二,2PC 两阶段提交 三,3PC 三段式提交 四,T 待我称王封你为后i/ 2022年11月27日 15:40/ 0 赞/ 374 阅读
相关 分布式事务01-分布式事务概述 文章目录 1.分布式事务产生的背景 1.1 分布式事务在不同场景下如何产生 1.2 案例 2.事务理论知识 2.1 AC 旧城等待,/ 2022年04月25日 09:54/ 0 赞/ 442 阅读
相关 分布式事务 一、前言 在单个数据库实例时候,我们可以使用一个数据源的事务([本地事务][Link 1] )来保证事务内的多个操作要么全部执行生效,要么全部不生效。在多数据库实例节点时 冷不防/ 2022年04月14日 02:09/ 0 赞/ 454 阅读
相关 分布式事务 什么是分布式事务 分布式事务涉及到操作多个数据库的事务,分布式事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于分布式系统的`不同节点上`。一个分布式事务可 Dear 丶/ 2022年03月10日 15:27/ 0 赞/ 357 阅读
相关 分布式事务 1、分布式事务产生的背景 在微服务环境下,因为会根据不同的业务会拆分成不同的服务,比如会员服务、订单服务、商品服务等,让专业的人做专业的事情,每个服务都有自己独立的数据库,并 - 日理万妓/ 2021年10月25日 14:09/ 0 赞/ 568 阅读
相关 分布式事务 阅读: 深入理解分布式事务,高并发下分布式事务的解决方案 [https://blog.csdn.net/qq\_32534441/article/details/890 红太狼/ 2021年10月13日 01:13/ 0 赞/ 573 阅读
相关 分布式事务 在分布式系统中,为了保证数据的高可用,通常,我们会将数据保留多个副本(replica),这些副本会放置在不同的物理的机器上。为了对用户提供正确的 CRUD 等语义,我们需... 灰太狼/ 2020年04月24日 17:42/ 0 赞/ 1041 阅读
还没有评论,来说两句吧...