什么是事务?
1:什么是事务?
事务(Transaction),一般是指要做的或所做的事情。
在计算机术语中:是指访问并可能更新数据库中各种数据项的一个程序执行单元 (unit)。事务通常由高级数据库操纵语言或编程语言(如SQL、C++、Java)书写的 用户程序的执行所引起,并用形如BeginTransaction和EndTransaction语句(或 函数调用来界定。
通俗讲:就是把多个要做的操作组合成一个整体,利用事务的特性来保证操作的安全性。如果一个事务做到一半出现任何错误,就会进行回滚操作,来恢复成最初的模样。
2:事务特性?
原子性(atomicity):事务是一个不可分割的工作单位,要么全部执行成功,要么全部不执行。只要其中一个指令执行失败,所有的指令都执行失败,数据进行回滚,回到执行指令前的数据状态;
一致性(consistency):事务的执行使数据从一个状态转换为另一个状态,但是对于整个数据的完整性保持稳定。即事务在完成时,必须是所有的数据都保持一致状态;
隔离性(isolation):一个事务的执行不能被其他事务所影响,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离;
持久性(durability):是指一个事务一旦正确完成后,它对数据库中数据的改变就是永久性的。
3:数据库事务(本地事务)
通过关系型数据库来控制事务,这是利用数据库本身的事务特性来实现的,因此叫数据库事务;由于应用主要靠关系数据库来控制事务,而数据库通常和应用在同一个服务器,所以基于关系型数据库的事务又被称为本地事务。
3.1:如何保证原子性?
开启事务:begin;
操作一:update table1 set ***;
操作二:update table2 set ***;
操作(***):其它写操作
提交事务:commit;
保证事务的原子性,就得等begin和commit之间的操作全部成功完成后,才将结果统一提交(commit)给数据库保存,如果途中任意一个操作失败,就撤销(rollback)前面的操作,且操作不会提交数据库保存,这样就保证了同生共死。
3.2:如何保证隔离性?
事务A:针对table1数据a,table3进行读写操作
事务B:针对table1数据a,table2进行读写操作
保证原子性的前提下,为了确保数据操作一致性不被破坏,需要数据的隔离机制,确保同时只能有一个事务A操作table1的数据a,事务A操作完了,另一个事务B才能操作table1的数据a。这需要对数据A加上互斥锁。
先获得了锁,然后才能修改对应的数据a,事务A完成后释放锁,给下一个要修改数据a的事务B,同一时间,只能有一个事务持有数据a的互斥锁,没有获取到锁的事务,需要等待锁释放
【注意】:在事务中更新某条数据获得的互斥锁,只有在事务提交或失败之后才会释放,在此之前,其他事务是只能读,不能写这条数据。
3.2.1:隔离性的四个级别
1.读未提交 read uncommitted:【会产生的问题:脏读、不可重复读、幻读】
2.读已提交 read committed(Oracle、PostgreSQL、SQL Server默认):【会产生的问题:不可重复读、幻读】
3.可重复读 repeatable read(MySQL默认):【会产生的问题:幻读】
4.串行化 serializable(SQLite默认):【会产生的问题:可以解决所有问题】
【注意】:隔离级别从小到大,安全性越来越高,但是效率越来越低。但是一般情况下不会修改数据库默认的隔离级别,只有在极特殊情况下才会做出修改已解决一些特殊问题。
******小贴士******:
1.设置数据库的隔离级别一定要是在开启事务之前;
2.隔离级别的设置只对当前链接有效:
对于使用MySQL命令窗口而言,一个窗口就相当于一个链接,当前窗口设置的隔离级别只对当前窗口中的事务有效;
对于JDBC操作数据库来说,一个Connection对象相当于一个链接,而对于Connection对象设置的隔离级别只对该Connection对象有效,与其他链接Connection对象无关。
3.2.2:并发事务导致的问题?
第一类丢失更新:撤销一个事务时,把其他事务已提交的更新数据覆盖
例:事务T1对表table1的一条数据状态“1”的数据更新为“2”操作,未提交;同时事务T2读取这条数据并且将状态“2”更新为“3”,然后提交;这是事务T1因未知原因进行撤销操作,这是该数据状态变更为事务T1为操作的状态“1”。
脏读:脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据
例:原始数据100,事务T1针对原始数据操作100-80(未提交),同时事务T2读取数据为20(事务T2实际数据需求为50,20不满足要求并结束事务),此时事务T1进行了回滚操作,数据实际仍为100。事务T2读到了事务1的未提交数据。
幻读也叫虚读:一个事务执行两次查询,第二次结果集包含第一次中没有或某些行已经被删除的数据,造成两次结果不一致,只是另一个事务在这两次查询中间插入或删除了数据造成的。幻读是事务非独立执行时发生的一种现象
例:事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。
不可重复读:一个事务两次读取同一行的数据,结果得到不同状态的结果,中间正好另一个事务更新了该数据,两次结果相异,不可被信任
例:事务T1在读取某一数据,而事务T2立马修改了这个数据并且提交事务给数据库,事务T1再次读取该数据就得到了不同的结果,发生了不可重复读。
第二类丢失更新:是不可重复读的特殊情况。如果两个事物都读取同一行,然后两个都进行写操作,并提交,第一个事物所做的改变就会丢失
例:
******小贴士******:
不可重复读和脏读的区别:脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据
幻读和不可重复读都是读取了另一条已经提交的事务,所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)
重复读:就是在开始读取数据(事务开启)时,不再允许修改操作
3.3:如何保证持久性?
如果在事务提交后,事务的数据还没有真正落到磁盘上,此时数据库奔溃了,事务对应的数据会不会丢?
事务会保证数据不会丢,当数据库因不可抗拒的原因奔溃后重启,它会保证:
成功提交的事务,数据会保存到磁盘
未提交的事务,相应的数据会回滚
3.3.1:事务日志
数据库通过事务日志来达到持久性数据不会丢这个目标。
事务的每一个操作(增/删/改)产生一条日志,内容组成大概如下:
LSN:一个按时间顺序分配的唯一日志序列号,靠后的操作的LSN比靠前的大。
TransID:产生操作的事务ID。
PageID:被修改的数据在磁盘上的位置,数据以页为单位存储。
PrevLSN:同一个事务产生的上一条日志记录的指针。
UNDO:取消本次操作的方法,按照此方法回滚。
REDO:重复本次操作的方法,如有必要,重复此方法保证操作成功。
磁盘上每个页(保存数据的,不是保存日志的)都记录着最后一个修改该数据操作的LSN。数据库会通过解析事务日志,将修改真正落到磁盘上(写盘),随后清理事务日志(正常情况下):
在保证数据安全及安全的前提下,避免写盘导致数据丢失(数据库崩盘)或写盘产生大量IO影响性能的办法:
1.将数据的变更以事务日志的方式,按照时间先后追加到日志缓冲区,由特定算法写入事务日志,这是顺序IO,性能较好
2.通过数据管理器解析事务日志,由特定的算法择机进行写盘
3.3.2:数据库恢复
当因数据库崩盘或其他原因进行数据恢复时,有以下几个过程:
1.解析存在的事务日志,分析哪些事务需要回滚,哪些需要写盘(还没来得及写盘,数据库就崩溃了)
2.Redo,进行写盘。检测对应数据所在数据页的LSN,如果数据页的LSN>=事务操作的LSN,说明已经写过盘,不然进行写盘操作
3.Undo, 按照LSN倒序进行回滚
4:分布式事务(CAP、两阶段提交、三阶段提交)
4.1:什么是分布式?
分布式系统会把一个应用系统拆分为可独立部署的多个服务,因此需要服务与服务之间远程协作才能完成事务操作,这种分布式系统环境下由不同的服务之间通过网络远程协作完成事务称之为分布式事务。
4.1.1:优势与不足
优势:解决集中式不便扩展的弊端,提供了便捷的扩展性、独立的服务治理,并提高了安全可靠性;
不足:增加了系统的复杂性,如分布式事务、分布式锁、分布式session、数据一致性等都是现在分布式系统中需要解决的难题。
4.1.2:分布式环境的事务复杂性
存储端的多样性:本地事务的情况下,所有数据都会落到同一个DB中,但是,在分布式的情况下,就会出现数据可能要落到多个DB,或落到Redis,或落到MQ等中;
事务链路的延展性:本地事务的情况下,通常所有事务相关的业务操作,会被我们封装到一个Service方法中。而在分布式的情况下,请求链路被延展,拉长,一个操作会被拆分成多个服务,它们呈现线状或网状,依靠网络通信构建成一个整体。
4.1.3:分布式环境产生分布式事务的场景
跨JVM进程产生(微服务化):微服务之间通过远程调用完成事务操作;
跨数据库实例产生务(跨库事务\分库分表):当单体系统需要访问多个数据库时就会产生分布式事务;
多服务访问同一个数据库实例:跨JVM进程,两个微服务持有了不同的数据库链接对同一数据库操作。
4.2:什么是分布式事务?
分布式事务:就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上(即:分布式场景下 一次完整的操作由不同的action组成,这些actions可能分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些action要么全部成功,要么全部失败,保证单个完整操作的原子性)。
本质上来说,分布式事务就是为了保证不同数据库的数据一致性
4.2.1:CAP理论
CAP定理(也称为Brewer定理)是由加州大学伯克利分校Eric Brewer教授提出来的,他指出WEB服务无法同时满足一下3个属性:
一致性(Consistency) : 客户端知道一系列的操作都会同时发生(生效),所有实例节点同一时间看到是相同的数据
可用性(Availability) : 不管是否成功,每个操作都必须以可预期的响应结束,且不会出现响应超时或响应错误
分区容错性(Partition tolerance) : 即使出现单个组件无法可用,操作依然可以完成(分区容忍性分是布式系统具备的基本能力)
具体地讲在分布式系统不可能同时满足以上三种。最多只能同时满足其中的两项,因为很多时候P是必须的, 因此往往选择就在CP或者AP中。
4.2.1.1:一致性
数据一致性指“all nodes see the same data at the same time”,即更新操作成功并返回客户端完成后,所有节点在同一时间的数据完全一致,不能存在中间状态。
数据一致性分为强一致性、弱一致性、最终一致性:
1. 强一致性:当用户的操作完成之后,会立马被同步到不同的数据副本中,后续其他任意请求都会获得更新过的值。这种对用户的可见性是最友好的,能始终保证读到正确的值。根据CAP理论,这种实现需要牺牲可用性;
2. 弱一致性:系统并不保证所有请求的访问都会获得最新值。数据写入成功之后,不承诺立即可以读,也不承诺具体多久之后可以读到,甚至读不到。在请求获得数据更新的这段时间,允许存在部分数据不一致,我们称之为“不一致性窗口”;
3. 最终一致性:是弱一致性的一种。系统保证在没有后续更新的前提下,系统最终返回上一次更新操作的值。在没有故障发生的前提下,不一致窗口的时间主要受通信延迟,系统负载和复制副本的个数影响,允许存在中间状态,只要求经过一段时间后,数据最终是一致的。
常见的事务处理机制:
Master-Slave 主从复制:写请求由Master负责,写入Master后,由Master同步到Slave上(异步同步,所以是弱/最终一致性)
Master-Master 主主复制:异步同步,最终的一致性,多个节点间需要序列化协议
4.2.1.2:可用性
系统提供的服务必须一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。
两个度量的维度:
1. 有限时间内:对于用户的一个操作请求,系统必须能够在指定的时间(响应时间)内返回对应的处理结果,**如果超过了这个时间范围,那么系统就被认为是不可用的**(即这个响应时间必须在一个合理的值内,不让用户感到失望);
2. 返回正常结果:要求系统在完成对用户请求的处理后,返回一个正常的响应结果。正常的响应结果通常能够明确地反映出对请求的处理结果,即成功或失败,而不是一个让用户感到困惑的返回结果(比如返回一个系统错误如OOM,则认为系统是不可用的)。
4.2.1.3:分区容错性
即分布式系统在遇到任何网络分区故障时,仍然需要能够保证对外提供满足一致性和可用性的服务,除非是整个网络环境都发生了故障。
4.2.1.4:CAP和ACID中的A和C是完全不一样的
A的区别:
ACID中的A指的是原子性(Atomicity),是指事务被视为一个不可分割的最小工作单元,事务中的所有操作要么全部提交成功,要么全部失败回滚;
CAP中的A指的是可用性(Availability),是指集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求;
C的区别:
ACID一致性是有关数据库规则,数据库总是从一个一致性的状态转换到另外一个一致性的状态;
CAP的一致性是分布式多服务器之间复制数据令这些服务器拥有同样的数据,由于网速限制,这种复制在不同的服务器上所消耗的时间是不固定的,集群通过组织客户端查看不同节点上还未同步的数据维持逻辑视图,这是一种分布式领域的一致性概念;
ACID里的一致性指的是事务执行前后,数据库完整性;而CAP的一致性,指的是分布式节点的数据的一致性。
4.2.2:BASE定理
CAP是分布式系统设计理论,BASE是CAP理论中AP方案的延伸,对于C我们采用的方式和策略就是保证最终一致性;
BASE是Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)三个短语的缩写。BASE基于CAP定理演化而来,核心思想是即时无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。
4.2.2.1:基本可用(Basically Available)
基本可用是指分布式系统在出现不可预知的故障的时候,允许损失部分可用性,但不等于系统不可用。
1. 响应时间上的损失:当出现故障时,响应时间增加
2. 功能上的损失:当流量高峰期时,屏蔽一些功能的使用以保证系统稳定性(服务降级)
4.2.2.2:软状态(Soft state)
与硬状态相对,即是指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时。
4.2.2.3:最终一致性(Eventually consistent)
强调系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。其本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。
最终一致性可分为如下几种:
1. 因果一致性(Causal consistency):即进程A在更新完数据后通知进程B,那么之后进程B对该项数据的范围都是进程A更新后的最新值;
2. 读己之所写(Read your writes):进程A更新一项数据后,它自己总是能访问到自己更新过的最新值;
3. 会话一致性(Session consistency):将数据一致性框定在会话当中,在一个会话当中实现读己之所写的一致性。即执行更新后,客户端在同一个会话中始终能读到该项数据的最新值;
4. 单调读一致性(Monotonic read consistency):如果一个进程从系统中读取出一个数据项的某个值后,那么系统对于该进程后续的任何数据访问都不应该返回更旧的值;
5. 单调写一致性(Monotoic write consistency):一个系统需要保证来自同一个进程的写操作被顺序执行。
4.2.2.4:BASE理论与CAP的关系
BASE理论的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。
BASE理论其实就是对CAP理论的延伸和补充,主要是对AP的补充。牺牲数据的强一致性,来保证数据的可用性,虽然存在中间装填,但数据最终一致。
4.2.2.5:ACID 和 BASE 的区别与联系
区别:
ACID 是传统数据库常用的设计理念,追求强一致性模型。
BASE 支持的是大型分布式系统,提出通过牺牲强一致性获得高可用性。
联系:
ACID 和 BASE 代表了两种截然相反的设计哲学,在分布式系统设计的场景中,系统组件对一致性要求是不同的,因此 ACID 和 BASE 又会结合使用。
4.3:分布式事务分类
分布式一致性问题的解决思路有两种,一种是分布式事务,一种是尽量通过业务流程避免分布式事务。分布式事务是直接解决问题,而业务规避其实通过解决出问题的地方。真实业务场景中,业务规避不是很麻烦的前提,最优雅的解决方案就是业务规避。
分布式事务分类:
1. 刚性事务满足CAP的CP理论(原则);
2. 柔性事务满足BASE理论(基本可用,最终一致)。
4.3.1:刚性事务【XA 协议(2PC/3PC、JTA、JTS)】
通常无业务改造,要使分布式事务达到像本地式事务一样,具备数据强一致性,原生支持回滚/隔离性,低并发,适合短事务(由于同步阻塞,处理效率低,不适合大型网站分布式场景)。
4.3.1.1:刚性事务-XA模型(X/Open DTP模型)
X/Open DTP(Distributed Transaction Process) 是一个分布式事务模型。这个模型主要使用了两段提交(2PC - Two-Phase-Commit)来保证分布式事务的完整性。
X/Open DTP模型的三个角色:
AP: Application应用程序,也就是业务层,哪些操作属于一个事务,就是AP定义的;
TM: Transaction Manager事务管理器,接收AP的事务请求,对全局事务进行管理,管理事务分支状态,协调RM的处理,通知RM哪些操作属于哪些全局事务以及事务分支等等,这个也是整个事务调度模型的核心部分;
RM:Resource Manager资源管理器,一般是数据库,也可以是其他的资源管理器,如消息队列(如JMS数据源),文件系统等。
其中:AP自己操作TM,当需要事务时,AP向TM请求发起事务,TM负责整个事务的提交,回滚等
4.3.1.2:刚性事务-XA规范
XA规范(XA Specification) 主要定义了(全局)事务管理器(Transaction Manager)和(局部)资源管理器(Resource Manager)之间的接口;目的是允许的多个资源(如数据库,应用服务器,消息队列等)在同一事务中访问,这样可以使 ACID 属性跨越应用程序而保持有效。目前知名的数据库,如Oracle, DB2,mysql等,都是实现了XA接口的,都可以作为RM。
XA规范使用两阶段提交(2PC,Two-Phase Commit)协议来保证所有资源同时提交或回滚任何特定的事务。
XA是数据库的分布式事务,强一致性,在整个过程中,数据一张锁住状态,即从prepare到commit、rollback的整个过程中,TM一直把持折数据库的锁,如果有其他人要修改数据库的该条数据,就必须等待锁的释放,存在长事务风险。
XA各阶段处理流程函数:
1. xa_open,xa_close:建立和关闭与资源管理器的连接;
2. xa_start,xa_end:开始和结束一个本地事务;
3. xa_prepare,xa_commit,xa_rollback:预提交、提交和回滚一个本地事务;
4. xa_recover:回滚一个已进行预提交的事务;
5. ax_reg,ax_unreg:允许一个资源管理器在一个TMS(TRANSACTION MANAGER SERVER)中动态注册或撤消注册。
其中,ax_开头的函数使资源管理器可以动态地在事务管理器中进行注册,并可以对XID(TRANSACTION IDS)进行操作
4.3.2:柔性事务【XA 协议(AP)】
在电商领域等互联网场景下,刚性事务在数据库性能和处理能力上都暴露出了瓶颈。
柔性事务有两个特性:基本可用和柔性状态
1. 基本可用是指分布式系统出现故障的时候允许损失一部分的可用性;
2. 柔性状态是指允许系统存在中间状态,这个中间状态不会影响系统整体的可用性,比如数据库读写分离的主从同步延迟等。柔性事务的一致性指的是最终一致性。
柔性事务主要分为补偿型(TCC、Saga)和通知型(MQ事务消息、最大努力通知型)。
4.3.2.1:柔性事务-通知型事务(异步)
通知型事务的主流实现是通过MQ(消息队列)来通知其他事务参与者自己事务的执行状态,引入MQ组件,有效的将事务参与者进行解耦,各参与者都可以异步执行,所以通知型事务又被称为异步事务。
异步事务场景分类
异步确保型事务:主要适用于内部系统的数据最终一致性保障,因为内部相对比较可控,如订单和购物车、收货与清算、支付与结算等等场景;
最大努力通知:主要用于外部系统,因为外部的网络环境更加复杂和不可信,所以只能尽最大努力去通知实现数据最终一致性,比如充值平台与运营商、支付对接等等跨网络系统级别对接。
4.3.2.1.1:异步确保型事务
指将一系列同步的事务操作修改为基于消息队列异步执行的操作,来避免分布式事务中同步阻塞带来的数据操作性能的下降。
有一些第三方的MQ是支持事务消息的,这些消息队列支持半消息机制,比如RocketMQ和ActiveMQ;但是有一些常用的MQ也不支持事务消息,比如RabbitMQ和Kafka 都不支持。
MQ事务消息方案
基于MQ的事务消息方案主要依靠MQ的半消息机制来实现投递消息和参与者自身本地事务的一致性保障。半消息机制实现原理其实借鉴的2PC的思路,是二阶段提交的广义拓展。
半消息:在原有队列消息执行后的逻辑,如果后面的本地逻辑出错,则不发送该消息,如果通过则告知MQ发送;
消息处理流程:
1. 事务发起方首先发送半消息到MQ;
2. MQ通知发送方消息发送成功;
3. 在发送半消息成功后执行本地事务;
4. 根据本地事务执行结果返回commit或者是rollback;
5. 如果消息是rollback, MQ将丢弃该消息不投递;如果是commit,MQ将会消息发送给消息订阅方;
6. 订阅方根据消息执行本地事务;
7. 订阅方执行本地事务成功后再从MQ中将该消息标记为已消费;
8. 如果执行本地事务过程中,执行端挂掉,或者超时,MQ服务器端将不停的询问producer来获取事务状态;
9. Consumer端的消费成功机制有MQ保证;
基于阿里 RocketMQ实现MQ异步确保型事务:
基于DB本地消息表方案
本地消息表最初由eBay提出来解决分布式事务的问题。是目前业界使用的比较多的方案之一,它的核心思想就是将分布式事务拆分成本地事务进行处理。
本地消息表处理逻辑:
1. 发送消息方:
需要有一个消息表,记录着消息状态相关信息;
业务数据和消息表在同一个数据库,要保证它俩在同一个本地事务。直接利用本地事务,将业务数据和事务消息直接写入数据库;
在本地事务中处理完业务数据和写消息表操作后,通过写消息到 MQ 消息队列。使用专门的投递工作线程进行事务消息投递到MQ,根据投递ACK去删除事务消息表记录;
消息会发到消息消费方,如果发送失败,即进行重试;
2. 消息消费方:
处理消息队列中的消息,完成自己的业务逻辑;
如果本地事务处理成功,则表明已经处理成功了;
如果本地事务处理失败,那么就会重试执行;
如果是业务层面的失败,给消息生产方发送一个业务补偿消息,通知进行回滚等操作;
4.3.2.1.2:最大努力通知事务
最大努力通知方案的目标:就是发起通知方通过一定的机制,最大努力将业务处理结果通知到接收方。
最大努力通知型的最终一致性本质:是通过引入定期校验机制实现最终一致性,对业务的侵入性较低,适合于对最终一致性敏感度比较低、业务链路较短的场景。
基于MQ自身的事务消息方案
基于DB的本地事务消息表方案
4.3.2.1.3:最大努力通知事务 VS 异步确保型事务
主要有的是业务差别,如下:
• 从参与者来说:最大努力通知事务适用于跨平台、跨企业的系统间业务交互;异步确保型事务更适用于同网络体系的内部服务交付。
• 从消息层面说:最大努力通知事务需要主动推送并提供多档次时间的重试机制来保证数据的通知;而异步确保型事务只需要消息消费者主动去消费。
• 从数据层面说:最大努力通知事务还需额外的定期校验机制对数据进行兜底,保证数据的最终一致性;而异步确保型事务只需保证消息的可靠投递即可,自身无需对数据进行兜底处理。
4.3.2.2:柔性事务-补偿型事务(同步)
4.3.2.2.1:什么是补偿模式?
补偿模式使用一个额外的协调服务来协调各个需要保证一致性的业务服务,协调服务按顺序调用各个业务微服务,如果某个业务服务调用异常(包括业务异常和技术异常)就取消之前所有已经调用成功的业务服务。
补偿模式大致有 TCC 和 Saga 两种细分的方案
4.3.2.2.2:什么是TCC事务模型?
TCC(Try-Confirm-Cancel)的概念来源于 Pat Helland 发表的一篇名为“Life beyond Distributed Transactions:an Apostate’s Opinion”的论文。
TCC 分布式事务模型包括三部分:
1. 主业务服务:主业务服务为整个业务活动的发起方,服务的编排者,负责发起并完成整个业务活动。
2. 从业务服务:从业务服务是整个业务活动的参与方,负责提供 TCC 业务操作,实现初步操作(Try)、确认操作(Confirm)、取消操作(Cancel)三个接口,供主业务服务调用。
3. 业务活动管理器:业务活动管理器管理控制整个业务活动,包括记录维护 TCC 全局事务的事务状态和每个从业务服务的子事务状态,并在业务活动提交时调用所有从业务服务的 Confirm 操作,在业务活动取消时调用所有从业务服务的 Cancel 操作。
TCC的工作流程:TCC(Try-Confirm-Cancel)分布式事务模型相对于 XA 等传统模型,其特征在于它不依赖资源管理器(RM)对分布式事务的支持,而是通过对业务逻辑的分解来实现分布式事务。
Try 阶段: 调用 Try 接口,尝试执行业务,完成所有业务检查,预留业务资源。
Confirm 或 Cancel 阶段: 两者是互斥的,只能进入其中一个,并且都满足幂等性,允许失败重试(如果重试失败,则需要人工介入进行恢复和处理等)。
Confirm 操作: 对业务系统做确认提交,确认执行业务操作,不做其他业务检查,只使用 Try 阶段预留的业务资源。
Cancel 操作: 在业务执行错误,需要回滚的状态下执行业务取消,释放预留资源。
4.3.2.2.3:什么是SAGA长事务模型?
Saga可以看做一个异步的、利用队列实现的补偿事务。
Saga模型是把一个分布式事务拆分为多个本地事务,每个本地事务都有相应的执行模块和补偿模块(对应TCC中的Confirm和Cancel),当Saga事务中任意一个本地事务出错时,可以通过调用相关的补偿方法恢复之前的事务,达到事务最终一致性。牺牲了一定的隔离性和一致性的,但是提高了long-running事务的可用性。
Saga 模型由三部分组成:
1. LLT(Long Live Transaction):由一个个本地事务组成的事务链;
2. 本地事务:事务链由一个个子事务(本地事务)组成,LLT = T1+T2+T3+...+Ti;
3. 补偿:每个本地事务 Ti 有对应的补偿 Ci。
Saga的执行顺序有两种:
1. T1, T2, T3, ..., Tn;
2. T1, T2, ..., Tj, Cj,..., C2, C1,其中0 < j < n。
本文来自博客园,作者:Eason0520,转载请注明原文链接:https://www.cnblogs.com/ctt-freedom/p/16554381.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构