A系统调用B系统,B系统又调用了C系统,他们都操作了各自的数据库,如何保证事物一致?
其实要实现分布式事物就需要修改spring框架的@Transactional逻辑,使用到AOP切面技术将自定义连接对象反给spring,并重写commit()方法的逻辑,让spring不再根据本地的事物而判断是提交还是回滚,而是根据分布式事物组最终计算的结果来决定。
所以要完成以上的步骤就需要在commit()中开启多线程,让线程等待事务组返回结果,当事务组返回结果后再唤醒线程,然后在commit()中根据结果来执行提交或回滚。
所以要完成上面的步骤,就需要创建一个事务组,这个事物组可以抽取成一个单独的系统,只负责与各自分布式的系统进行通讯,它负责接收每个系统的事物状态,并统计到最后一个,最后计算只要里面包含了一个需要回滚的定义结果为rallback,否则结果为commit,之后便将这个结果在响应给子系统。这种方式可以使用MQ,也可以使用最普通的tomcat。
那么问题就来了,要完成上面的步骤,如何将子系统事物的状态发送给事务组呢?那么需要你自定义事物注解,并给这个注解定义一个切面,而且优先级最高,让方法执行之前最先执行这个切面,在切面方法的逻辑中获取事物注解的参数,生成事务组id,之后在调用spring的逻辑,执行@Transcational,这一步就必然会执行commit()方法,但是这个方法被线程等待了,所以不会立马执行。然后在这个切面方法中使用try的方式来判断执行是否成功,从而知道应该给事务组传commit还是rallback的指令。
最后当系统接收到事务组返回的最后的指令后,便可以唤醒等待的线程,commit()在根据返回的结果决定是提交还是回滚,就这样实现了分布式事物。