调用流程
捞一张官网的图,调用流程中大致有这么几个角色:
简单介绍下
- TM:全局事务发起一方
- TC:seata
- RM: 全局事务中被调用的一方
调用流程分析
下面叙述中的seata其实就是TC
- business服务启动时,GlobalTransactionScanner会对有@GlobalTransaction注解的方法进行AOP增强,并生成代理,增强的代码位于GlobalTransactionalInterceptor类中,当调用@GlobalTransaction注解的方法时,增强代码首先向TC注册全局事务,表示全局事务的开始,同时TC生成XID,并返回给TM(也就是business服务);
- business服务调用sotck和order服务时会发xid传递过去,作为整个全局事务的流水号,然后stocke和order服务会向seata注册分支事务,此时注册的分支事务中有xid信息,自然就可以和整个全局事务关联起来了。
- 被调用的stock服务在执行sql的时候,会将执行前的数据save一份,执行后的数据save一份,然后保存到本地库的undo_log表中。然后stock服务本地事务提交,通知seata当前分支事务成功。
- 被调用的order服务和被order服务调用的account服务的全局事务过程和stocke服务是一样的。
- 最后再business服务这边调用相关服务完成,接口返回数据(一般就是feign调用各个服务)。代码执行完之后business没有抛异常(business服务自己的本地库里的undo_log表同样也会记录sql执行前和执行后的数据),则通知seata全局事务成功,然后seata通知此时全局事务的相关方删除各自本地库中undo_log表里对应的数据。
- 如果business这边执行过程中出现异常(这个异常可能是被调用的服务跑抛的也可能是business服务自己抛的),则通知seata全局事务执行失败,然后seata通知当前全局事务相关方通过各自本地库中的undo_log表里关联的数据回滚。(如果在这个过程中被sql执行的数据,被其他线程修改过了,和undo_log表中记录的执行前后内容对不上了,此时seata回滚就会报错,此时需要人工介入)。