.分布式事务解决方案: -
补偿方式
在讲
- 之前先了解两个概念: 不完美补偿( )和完美补偿( )。. :不完美补偿,一般在系统中我们会专门为业务逻辑对应写一个补偿逻辑,如果业务逻辑执行失败,就会去执行这个补偿逻辑,我们称这个补偿逻辑为反向操作,这个反向操作同样会留下操作痕迹,例如:在银行系统中,客户去 取钱,银行会先对用户账户进行扣款操作,如果本次取钱不成功,银行系统会发出一笔冲正操作,将之前扣除的款项打回用户账户,这个冲正操作在交易记录里面是开源查询到的。
. :完美补偿, 阶段会彻底清楚之前的业务逻辑操作,用户是感知不到的。例如:在一个交易平台去发起交易,首先在 阶段不会直接去扣除账户余额,而且去检查用户的额度并刷新额度,然后在 阶段才去真正操作账户。如果出现异常,那么在 阶段就需要去执行业务逻辑来取消 阶段产生的后果,释放在 阶段被占用的额度。整个过程只有等 执行完毕,交易才算完成。
- 出自于华为微服务框架 ,是一个开源的分布式事务最终一致性解决方案,该项目已交由 软件基金会孵化,目前已经在 毕业了。 . . 版本之前叫 - ,现版本已经改名为 - 。
- 架构主要包含两个组件: 和 ;
•
: 其实就是一个 端,需要用户自行编译运行,它的作用就是上述中的分布式事务协调器,主要作用是和 客户端进行通讯,接收 发过来的事务事件,然后进行持久化存储事务以及修改协调子事务的状态,从而保证全局事务中的所有子事务状态都一致,即要么全执行完成,要么全执行失败。•
: 端其实可以看成是一个微服务中内嵌的 ,主要作用是监控本地子事务的执行情况并向 - 端发送子事务执行事件以及传递全局事务 ,并在异常情况下会根据 下发的操作事件进行相应的补偿操作。从上图中我们大致可以了解整个
- 是如何运转的,但是有一个疑问点, - 端是怎么知道多个 发送过来的子事务是属于同一个全局事务的呢?其实在分布式事务开始点会生成一个全局事务 ,然后在调用子事务所处的服务时,会把这个全局事务 传递给子事务,然后 端会会把这个全局事务 和 传递过来的子事务事件绑定并持久化到数据库中,这样就会形成一个完整的事务调用链,我们通过这个全局事务 就可以完整的追踪到整个分布式事务的执行情况。会以切面编程的方式向应用程序注入相关的处理模块,帮助我们构建分布式事务调用的上下文。 在事务处理初始阶段处理事务的相关准备的操作,在事务执行完毕做一些清理的操作,例如创建分布式事务起始事件,以及相关的子事件,根据事务的执行的成功或者失败生产相关的事务终止或者失败事件。这样带来的好处是用户的代码只需要添加几个 来描述分布式事务执行范围,以及与本地的事务处理恢复的相关函数信息, 就能通过切面注入的代码能够追踪与本地事务的执行情况。 会将本地事务执行的情况以事件的方式通知给 。 由于单个 不可能知晓一个分布式事务下其他参与服务的执行情况,这样就需要 扮演一个十分重要的协调者的角色。 将收集到的分布式事务事件信息整理汇总,通过分析这些事件之间的关系可以了解到分布式事务的执行情况, 通过向 下发相关的执行指令由 执行相关提交或恢复操作,实现分布式事务的最终一致性。
在了解的[ ]
实现的部分细节之后,我们可以从下图进一步了解 架构下, 与 内部各模块之间的关系图。整个架构分为三个部分,一个是,另外一个就是注入到微服务实例中的 协调器,以及 与 之间的交互协议,目前 支持 以及 两种分布式事务协调协议实现。
事务注解模块( ) 以及 事务拦截器( ); 分布式事务执行相关的事务上下文( ),事务回调( ) ,事务执行器( );以及负责与 进行通讯的事务传输( )模块。
包含了与分析用户分布式事务逻辑相关的• 事务注解模块是分布式事务的用户界面,用户将这些标注添加到自己的业务代码之上用以描述与分布式事务相关的信息,这样 就可以按照分布式事务的协调要求进行相关的处理。如果大家扩展自己的分布式事务,也可以通过定义自己的事务标注来实现。
• 事务拦截器这个模块我们可以借助 手段,在用户标注的代码基础上添加相关的拦截代码,获取到与分布式事务以及本地事务执行相关的信息,并借助事务传输模块与 进行通讯传递事件。
• 事务上下文为 内部提供了一个传递事务调用信息的一个手段,借助前面提到的全局事务 以及本地事务 的对应关系, 可以很容易检索到与一个分布式事务相关的所有本地事务事件信息。
• 事务执行器主要是为了处理事务调用超时设计的模块。由于 与 之间的连接有可能不可靠, 端很难判断 本地事务执行超时是由 与 直接的网络引起的还是 自身调用的问题,因此设计了事务执行器来监控 的本地的执行情况,简化 的超时操作。目前 的缺省实现是直接调用事务方法,由 的后台服务通过扫描事件表的方式来确定事务执行时间是否超时。
• 事务回调在 与 建立连接的时候就会向 进行注册,当 需要进行相关的协调操作的时候,会直接调用 注册的回调方法进行通信。由于微服务实例在云化场景启停会很频繁,我们不能假设 一直能找到原有注册上的事务回调,因此我们建议微服务实例是无状态的,这样 只需要根据服务名就能找到对应的 进行通信。
• 事务传输模块负责 与 之间的通讯,在具体的实现过程中, 通过定义相关的 描述接口文件定义了 以及 的事务交互方法,同时也定义了与交互相关的事件。[ ]