分布式事务的定义和理解
分布式事务其实就是两个事务的统一管理(为了保证数据的一致性,要么全部提交,要么全部回滚):
如:1.同一个数据库两个不同事务,不能通过事务的嵌套等操作进行统一管理,那么他们属于分布式事务。这种情况如:A系统调用B系统的接口,A,B系统共用同一个DB;A系统一方面操作本地DB,另一方面通过发送MQ消息进行自发自收操作DB,这样也组成了分布式事务。
2.会涉及到操作多个数据库的事务。可以是同一类型的数据库,如MySQL和MySQL,Oracle和Oracle;也可以不是同一类型的数据库,如MySQL和redis,MySQL和Oracle。
易误区:
例如,一个java进程,操作多个数据库,如redis,mysql等,虽然他们每个数据库都有自己的事务,但是我们也可以把对他们的操作放到一个java进程事务当中进行管理。
这不算分布式事务。分布式事务是要两个不同的java进程的操作一直所以一个事务进行原子性操作。
解答疑惑:一个java进程,操作多个数据库,如redis,mysql等,虽然他们在同一个java进程,但是他们都有自己的数据库事务,所以这属于分布式事务。
分布式事务:一种是强一致性(成功就完事,失败就回滚);另一种是最终一致性,如RocketMQ,如果是网络或者IO问题,MQ可以采取重试操作,时间久点没关系,努力达到事务最终的一致性;
如果是消费者那边的程序异常,那么消费者会进行了相应的回滚,然后它又想回滚生产者的事务,其实是无法自动做到的,只能通过后续的补偿,补丁修复了。一般处理方案是完善好消费者的代码程序,使之正常消费,同时也要考虑好
因为程序异常导致MQ消息堆积问题解决方案。
RPC模式与MQ模式的区别,RPC模式其实是请求应答模式,MQ模式就是只请求不响应模式。
服务或者接口的幂等性只是解决重复消费问题,解决不了程序异常的分布式事务问题。
如果系统间只是一些rpc远程调用,其中调用方本地的事务自己可以控制,但是被调用方事务要想回滚是无法做到的,可以通过支持事务的MQ进行补偿,补丁被调用方系统的数据。或者http补偿接口不断重试补偿,直到补偿事务执行成功为止。
如果多个系统之间调用采用rpc,mq(支持事务)混合,又有嵌套,如一个系统既是mq中的消费者,又是另外一个系统mq的生产者这种链路,消费中又有rpc调用。这种情况是不做分布式事务强一致性的,只做分布式事务最终一致性。尽可能保证系统的mq消息正常的消费,正常的发送mq消息,努力做到不抛异常,避免使之不断重试,导致消息堆积,rpc调用由于网络,IO原因,程序异常代码等等,暂时记录下来,不阻碍程序往下走,后续通过补偿这些,达到事务最终一致性就可以了。
总结:发送mq消息产生的分布式事务可以通过支持发送事务消息来达到分布式事务的最终一致性。对于rpc调用产生的分布式事务只能通过之后的补偿操作来处理。如果用了TCC框架可以保证强一致性,但是关联系统比较多,影响性能。所以有时候开发一个业务逻辑是用rpc还是要mq,需要对比考量的。需不需要返回值等,rpc有返回值,而mq没有。rpc中异步调用其实就是新起了一个线程。如果有的rpc调用不考虑
分布式事务强一致性,存在重试也要考虑进行接口服务的幂等处理。
rpc接口,mq消息的重试次数,接口设置的超时时间,超时之后的重试带来的消息重复消费引起的幂等性操作,是基于该服务接口不因为程序代码异常,经过1次,或者1次以上调用能够响应consumer那一端,然后对provider那一端没有影响。然后基于这个基础上对provider的service接口做相应的幂等性处理。
实际开发当中,rpc调用采用的策略为
超时+重试+幂等+补偿,超时,重试rpc中可以配置的,
幂等+补偿需要自己处理,事务mq只需要我们做好幂等就可以了,它会不断重试的,直到成功为止。