seata
- 前两篇文中总结了一下分布式事务已经现阶段常用的解决方案,现在来讨论一下现有的分布式事务框架seata,点击此处是seata的官网seata致力于微服务框架下提供高性能和简单易用的分布式事务服务。它提供了AT,TCC,Saga ,XA这几种事务模型,为开发者提供了一站式的分布式事务解决方案。其中TCC和XA我们上一篇文中已经有说明,接下来我们讨论一下Seata中AT和Saga这两种事务模型是怎么样的。
AT模式
- AT模式是Seata最主推的分布式事务解决方案,他是基于XA演进过来的一种分布式事务模式,随意他同样分为三大模块,分别是TM(Transaction Manager),RM(Resource Manager)和TC(Transaction Server),其中TM和RM作为Seata客户端与业务系统集成,TC作为Seata的服务器端独立部署,TM表示事务管理器,他负责向TC注册一个全局事务,并生成一个全局事务唯一XID。在AT模式下,每个数据库资源被称作一个RM,在业务层通过JDBC标准接口范问RM的时候,Seata会对所有请求进行拦截。每一个本地事务进行提交时候,RM都会想TC事务协调器注册一个分支事务。Seata的AT模式如下图说明:
- 具体流程如下:
- TM向TC注册一个全局的事务,并生成全局XID
- 期间整个业务流程内每个RM想TC注册分支事务,并将其纳入改XID对应的全局事务范围
- RM想TC汇报资源的准备状态
- TC汇总所有事务参与者的状态,决定分布式事务是全部回滚还是全部提交
- TC通知所有RM提交/回滚事务
- AT模式和XA模式一样,都是一个两阶段提交的事务模型,不过和XA相比,做了一些优化,这个官网着重讲解了一下AT的原理,之后开一节着重看下一AT模式的实现原理。
Saga模式
-
Saga模式是SEATA提供的长事务解决方案,这种理论模型是由普林斯顿大学的Hector Garcia-Molina 和 Kenneth Salem 提出的,主要描述的是在没有两阶段提交的前提下如何解决分布式事务问题。核心思想是:将一个业务流程中长事务拆分为多个本地的短事务,业务流程中每个参与者都提交正式的提交给本地短事务,当其中一个参与者事务执行失败,则通过补偿机制补偿签名已经成功的参与者。
-
如下图说明Saga由一系列sub-transaction Ti 组成,每个Ti 都有对应的补偿动作Ci ,补偿动作用于撤回Ti 造成的数据变化。和TCC相比,少了Try这一步,每个操作都是真实的数据库操作。
-
按照Saga的工作模式,有两种执行方式:
- T1, T2, T3, …,Ti: 这种方式表示所有事务都正常执行。
- T1, T2, …, Tj,Cj,…,C2,C1: 这种情况是表示执行到Tj的时候,Tj 事务出现异常,通过补偿操作撤销之前所有成功的sub-transaction
-
另外Saga还提供了一下两种补偿恢复方式:
- 向后恢复,也就是上面提到的第二中工作模式,如果任何一个子事务执行失败,则吧之前执行的结果逐个撤销
- 向前恢复,也就是不进行补偿,而是对失败的事务进行重试,这种方式比较适合事务必须要执行成功的场景。
Saga的优势
- 和XA和TCC比较,他的优势包括:一阶段直接提交本地事务;没有锁,没有锁,没有锁!!!,性能较高;在事件驱动的模式下,段事务可以异步执行;补偿机制的实现比较简单。
- 缺点是Saga并不提供原子性和隔离性支持,隔离性的影响是比较大的,比如用户购买一个情感课程后会赠送一段时间会员,或者赠送打折卷,如果用户在回滚之前将优惠券用掉了,会在在回滚之前使用了会员的一些特殊服务,那么事务出现异常回滚的时候就无法收回这部分,会出现业务上的问题。
Saga的实现方式
-
就像刚才的案例,用户购买情感课程,这个业务场景下会涉及到订单创建,课程库存的修改,微信支付,会员赠送,整个流程如下:
-
在以上支付下单的流程上一个典型的长事务,根据Saga模式的定义,先将长事务拆分成对个本地端事务,每个服务的本地事务按照执行顺序逐一提交,一旦其中一个服务的事务出现异常,则采用补偿的方式逐一撤回。这一过程的实现会设计Saga的协调模式,他有两种常用的协调模型。
- 事件/编排式:把Saga的决策和执行顺序逻辑分布在Saga的每一个参与者中,他们通过交换事件的方式来进行沟通
- 命令/协同式:把Saga的角色和执行顺序逻辑集中在一个Saga控制类中,他以命令/回复的方式与每一项服务进行通信,告诉他们应该执行哪个操作。
事件/编排式
- 在基于时间的编排模式中,第一个服务执行完一个本地事务之后,发送一个事件。这个事件会被一个或者多个服务监听,监听到事件的服务接着执行他自己的本地事务并发布新的事件,此后一直延续这种事件触发模式,直到整个业务流程中最后一个服务的本地事务执行结束,才意味着整个分布式长事务也执行结束。我们用如下图说明:
- 如上图流程看起来复杂,但是他是比较常见的解决方案,解释以上流程:
- 订单服务创建新的订单,吧订单状态设置为待支付,并发布一个“创建订单”事件
- 库存服务监听到 “创建订单”事件后,执行本地库存冻结方法,如果执行成功,则发布一个“库存准备事件”
- 支付服务监听到 “库存准备事件”事件后,执行账户扣款方法,并发布 “支付事件”
- 最后,积分服务监听到“支付事件”事件后,增加账户积分,并更新订单状态为成功
- 如果上述任何一次执行失败,当前时间都变成失败的时间,例如“库存准备事件” 变成 “库存准备失败事件”,每个服务需要监听失败的情况根据实际需求进行逐一回滚。
命令/协同式
- 命令/协同 模式需要定义一个Saga协调器,负责告诉每一个参与者该做啥。Saga协调器以命令/回复的方式与每一个服务进行通信,如下流程:
-
命令协同模式流程如下:
- 订单服务手下创建一个订单,然后创建一个订单的协调器,用来协调之后的事务,启动订单事务。
- Saga协调器向库存服务发送冻结库存命令,库存服务通过订单 Saga回复队列回复直接的结果
- 接着,Saga协调器继续向支付服务发起咋呼扣款命令,支付服务通过订单 Saga回复队列回复执行结果
- 最后,Saga协调器向会员服务发起添加会员命令,会员服务回复执行结果。
-
整个流程需要有一个前置条件,订单Saga协调器必须提前知道“创建订单事务”的所有流程,并且在整个流程中任何一个环节执行失败,他都需要向每个参与者发送命令,撤销之前的事务操作。
上一篇:分布式事务解决方案
下一篇:分布式事务 – seata框架AT模式实现原理