开源框架 seata
事务
通俗意义上事务就是为了使得一些更新操作要么都成功,要么都失败
ACID特性
原子性(Atomicity),可以理解为一个事务内的所有操作要么都执行,要么都不执行。
一致性(Consistency),可以理解为数据是满足完整性约束的,也就是不会存在中间状态的数据,比如你账上有400,我账上有100,你给我打200块,此时你账上的钱应该是200,我账上的钱应该是300,不会存在我账上钱加了,你账上钱没扣的中间状态。
隔离性(Isolation),指的是多个事务并发执行的时候不会互相干扰,即一个事务内部的数据对于其他事务来说是隔离的。
持久性(Durability),指的是一个事务完成了之后数据就被永远保存下来,之后的其他操作或故障都不会对事务的结果产生影响。
分布式事务
分布式事务顾名思义就是要在分布式系统中实现事务,它其实是由多个本地事务组合而成。如跨库事务、服务化事务。
XA规范
是指由 X/Open 组织提出的强一致性的分布式事务规范, XA 规范主要定义了事务管理器(Transaction Manager)和局部资源管理器(Resource Manager)之间的接口。
在XA规范之前,存在着一个DTP模型,该模型规范了分布式事务的模型设计。
AP(Application):应用系统(微服务)
TM(Transaction Manager):事务管理器(全局事务管理)
RM(Resource Manager):资源管理器(数据库)
DTP规范中主要包含了AP、RM、TM三个部分,其中AP是应用程序,是事务发起和结束的地方;RM是资源管理器,主要负责管理每个数据库的连接数据源;TM是事务管理器,负责事务的全局管理,包括事务的生命周期管理和资源的分配协调等。
二阶提交协议和三阶提交协议就是根据这一思想衍生出来的。可以说二阶段提交其实就是实现XA分布式事务的关键
2PC
两阶段提交协议(The two-phase commit protocol,2PC)是 XA 用于在全局事务中协调多个资源的机制。
所谓的两个阶段是指:第一阶段:准备阶段和第二阶段:提交阶段
- 第一阶段:RM执行各自事务并返回执行结果给TM但都不提交
- 第二阶段:TM根据第一阶段各个RM的事务执行情况决定提交或者回滚(所有参与者均反馈YES时,即提交事务,任何一个参与者反馈NO时,即中断事务)
缺点:同步阻塞、TM单点问题、可能由于网络问题造成数据不一致
3PC
三阶段提交(Three-phase commit),也叫三阶段提交协议(Three-phase commit protocol),是二阶段提交(2PC)的改进版本。
与两阶段提交不同的是,三阶段提交有两个改动点:
- 引入超时机制。同时在协调者和参与者中都引入超时机制。
- 在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。
也就是说,除了引入超时机制之外,3PC把2PC的准备阶段再次一分为二,这样三阶段提交就有CanCommit、PreCommit、DoCommit三个阶段。
- CanCommit:之前2PC的一阶段是本地事务执行结束后,最后不Commit,等其它服务都执行结束并返回Yes,由协调者发生commit才真正执行commit。协调者向参与者发送CanCommit请求,参与者如果可以提交就返回Yes响应,否则返回No响应。
- PreCommit:在阶段一中,如果所有的参与者都返回Yes的话,那么就会进入PreCommit阶段进行事务预提交。这里的PreCommit阶段 跟上面的第一阶段是差不多的,只不过这里 协调者和参与者都引入了超时机制 (2PC中只有协调者可以超时,参与者没有超时机制)。
- DoCommit:这里跟2pc的阶段二是差不多的。
优点:降低了阻塞范围,在等待超时后协调者或参与者会中断事务。避免了协调者单点问题,阶段3中协调者出现问题时,参与者会继续提交事务。
缺点:同样会有数据不一致的问题
TCC
TCC和2PC/3PC很像,不过TCC的事务控制都是业务代码层面的,而2PC/3PC则是资源层面的。
TCC事务其实主要包含三个阶段:Try、Confirm、Cancel阶段(不是必须执行)
TCC的核心思想是,try阶段检查并预留资源,确保在confirm阶段有资源可用,这样可以最大程度的确保confirm阶段能够执行成功。
Try 阶段:这个阶段说的是对各个服务的资源做检测以及对资源进行锁定或者预留。
Confirm 阶段:这个阶段说的是在各个服务中执行实际的操作。
Cancel 阶段:如果任何一个服务的业务方法执行出错,那么这里就需要进行补偿,就是执行已经执行成功的业务逻辑的回滚操作
优点:解决了协调者单点,由主业务方发起并完成这个业务活动。业务活动管理器也变成多点,引入集群。
同步阻塞: 引入超时,超时后进行补偿,并且不会锁定整个资源,将资源转换为业务逻辑形式,粒度变小。
数据一致性,有了补偿机制之后,由业务活动管理器控制一致性。
缺点:在Confirm,Cancel中都有可能失败。TCC属于应用层的一种补偿方式,所以需要程序员在实现的时候多写很多补偿的代码,在一些场景中,一些业务流程可能用TCC不太好定义及处理。
SAGA
Saga模式是一种分布式异步事务,一种最终一致性事务。
Saga 是 30 年前一篇数据库伦理提到的一个概念。其核心思想是将长事务拆分为多个本地短事务,由 Saga 事务协调器协调,如果正常结束那就正常完成,如果某个步骤失败,则根据相反顺序一次调用补偿操作。
Saga是由一系列的本地事务构成。每一个本地事务在更新完数据库之后,会发布一条消息或者一个事件来触发Saga中的下一个本地事务的执行。如果一个本地事务因为某些业务规则无法满足而失败,Saga会执行在这个失败的事务之前成功提交的所有事务的补偿操作。
Saga的实现有很多种方式,其中最流行的两种方式是:
- 基于事件的方式:在基于事件的方式中,第一个服务执行完本地事务之后,会产生一个事件。其它服务会监听这个事件,触发该服务本地事务的执行,并产生新的事件。
- 基于命令的方式:在基于命令的方式中,我们会定义一个新的服务,这个服务扮演的角色就和一支交响乐乐队的指挥一样,告诉各个业务参与方,在什么时候做什么事情。我们管这个新服务叫做协调中心。协调中心通过命令/回复的方式来和Saga中其它服务进行交互。
Seata AT
AT 模式是一种无侵入的分布式事务解决方案。在 AT 模式下,用户只需关注自己的“业务 SQL”,用户的 “业务 SQL” 作为一阶段,Seata 框架会自动生成事务的二阶段提交和回滚操作
AT 模式(参考链接 TBD)基于 支持本地 ACID 事务 的 关系型数据库:
- 一阶段 prepare 行为:在本地事务中,一并提交业务数据更新和相应回滚日志记录。
- 二阶段 commit 行为:马上成功结束,自动 异步批量清理回滚日志。
- 二阶段 rollback 行为:通过回滚日志,自动 生成补偿操作,完成数据回滚。
本地消息表
基本思路就是:
消息生产方,需要额外建一个消息表,并记录消息发送状态。消息表和业务数据要在一个事务里提交,也就是说他们要在一个数据库里面。然后消息会经过MQ发送到消息的消费方。如果消息发送失败,会进行重试发送。
消息消费方,需要处理这个消息,并完成自己的业务逻辑。此时如果本地事务处理成功,表明已经处理成功了,如果处理失败,那么就会重试执行。如果是业务上面的失败,可以给生产方发送一个业务补偿消息,通知生产方进行回滚等操作。
MQ事务消息
主要用来保证本地事务和消息发送,要么同时成功要么同时失败
a.生产者向我们的Broker(MQ服务器端)发送我们派单消息设置为半事务消息,该消息不可以被消费者消费。
b.在执行我们的本地的事务,将本地执行事务结果提交或者回滚告诉Broker
c.Broker获取本地事务的结果如果是已提交的话,将该半消息设置为允许被消费者消费,如果本地事务执行失败的情况下,将该半消息直接从Broker中移除
d.如果我们的本地事务没有将结果及时通知给我们的Broker,这时候我们Broker会主动定时(默认60s)查询本地事务结果
e.本地事务结果实际上就是一个回调方法,根据自己业务场景封装本地事务结果
事务回查的时间次数等配置在broker里
RocketMQ如何解决分布式事务