EasyTransaction一站式解决分布式 SOA 事务问题
一、由来
这个框架是结合齐牛金融公司之前遇到的分布式事务场景以及 支付宝程立分享的一个PPT<大规模SOA系统的分布式事务处理>而设计实现,意在解决之前公司对于每个分布式事务场景中都自行重复设计中间状态、幂等实现及重试逻辑的状况。采纳本框架后能解决现有已发现的所有分布式事务场景,减少设计开发设计工作量,提高开发效率,并统一保证事务实现的可靠性。
二、分布式事务场景及框架对应实现
分布式事务场景
无需分布式事务
最常用
最优先使用
使用消息队列完成的最终一致性事务
适用于业务主逻辑无需外部数据变更协助来完成的最终一致性事务
常见
若一定要与其他服务写接口发生交互,则优先使用
依据是否保证投递到订阅者,分为可靠消息及最大努力交付消息
有时业务需求一些本质是异步操作,但是尽可能同步返回结果,这本质也归属于这一类,但介于其有返回值,同步时可返回结果,其有区别于可靠消息。
使用传统补偿完成的最终一致性事务
适用于需要获知远程执行结果来决定逻辑事务走向 且 可以进行补偿的业务
次常见
若使用消息队列不能解决的事务问题优先考虑使用基于补偿的最终一致性事务
使用TCC完成最终一致性事务
适用于需要获知远程执行结果来决定逻辑事务走向 且 不可以进行补偿的业务
最不常见
最终解决办法,囊括所有必须使用2PC实现的场景。编码量最大,性能消耗最大,应尽量避免使用本类型的事务
框架对应实现及基本原理
框架实现了上述所有事物场景的解决方案,并提供了统一易用的接口。以下介绍基本实现原理
无需分布式事务
对于此类事务,框架完全不介入,不执行一行额外代码
其他事务场景
框架的核心依赖是Spring的TransactionSynchronization,只要使用的事务管理器继承自AbstractPlatformTransactionManager都能使用本框架(基本上都集成自本实现)。
对于分布式事务,框架会在调用远程事务方法后,将对应的框架操作挂载到TransactionSynchronization中,如:
使用消息队列完成的最终一致性事务,框架将会在事务COMMIT后发发送消息,保证只有COMMIT后事务才能被外部看见,这里也省去业务开发者对于 发送-确认-检测 类型 队列实现的代码量
使用TCC完成最终一致性事务,框架将会根据事务的实际完成情况调用Confirm或者Cancel,用传统补偿完成的最终一致性事务也类似
框架有后台线程负责CRASH恢复,其根据“在执行分布式服务调用前写入的WriteAheadLog获得可能已经调用的业务”以及“跟随业务一起提交的一条框架记录以确认的业务最终提交状态”来进行最终的CRASH具体操作(如TCC的Confirm或者Rollback)
框架对于幂等也有完整的实现(可选),框架能保证业务方法逻辑上只执行一遍(有可能执行多遍,但多次执行的方法会被回滚掉,因此,涉及不可回滚的外部资源时,业务程序需自行把控其幂等性)
框架对于方法间有调用关系依赖的也进行妥善的处理,例如基于传统补偿完成的最终一致性事务中
业务方法没有被调用,那么补偿方法对应的业务实现也不会被调用(但框架仍会记录下补偿方法已经被调用过)
补偿方法已经被掉用过了,那么业务方法无论曾经有没有被执行过,都不会被调用
所有远程调用的结果都是以Future形式返回,这给框架的性能优化提供了空间,在第一次获取结果前,所有的日志都不会被写入所有远程方法都不会被调用。一旦业务程序尝试获取执行结果时,才会批量写入日志及后续并发调用远程方法。
如果业务程序没有尝试获取执行结果,框架COMMIT前会统一尝试GET一遍,对于所有远程方法一旦抛出了Exception,框架都会在最后commit前将业务回滚,而无论之前是否catch住了,这样能保证编程模型的简洁,方便写出正确易理解的代码。