1 缘起
补充事务相关知识过程中,
发现,默认的知识都是基于单体服务的事务,比如ACID,
然而,在一些复杂的业务系统中,采用微服务架构构建各自的业务,
就有了分布式事务的概念,比如,一致性在单体服务和分布式服务中的场景是有一定差别的,
但是,都是为了尽最大努力保证:原子性、一致性、持久化,
单体服务中事务的一致性是强一致性,而分布式服务的事务一致性会分为:强一致性、弱一致性和最终一致性,
因此,有必要学习下分布式事务相关的知识,
分享如下,帮助轻松应对知识交流和考核。
单体服务事务相关文章:
https://blog.csdn.net/Xin_101/article/details/102246522
https://blog.csdn.net/Xin_101/article/details/102240949
2 分布式事务
2.1 为什么
为什么会有分布式事务?
既是业务问题,又是技术问题。随着业务的多元化与复杂度的增加,在技术实现层面进行了合理的业务划分,当完成业务划分后,本应该在一个会话或命令空间中的操作,散落到各个服务中,于是,有了分布式事务相关的问题。
有人会想,这不是自己给自己挖坑吗?为什么要把服务分开,都在一起不就好了?其实,对于技术实现而言,只有相对合理,没有绝对边界,在这里挖坑的土,可能是填另外一个坑的原料,虽然业务拆分有分布式等相关问题,但是,也解决了一部分其他问题,比如服务耦合、服务庞大一荣俱荣,一损俱损等(微服务带来的优势)。
关于为什么有分布式事务这个问题以及方案,不同的业务会有不同见解,不是所有业务都要考虑分布式相关的问题,因地制宜即可,我们在学习或研究某些方案的过程中,不见得会立马用到,而是为了填充我们的知识库,当遇到问题时,多一些思路,多一些方案,最终解决问题。
2.2 方案
分布式事务方案可分为两类。
(1)基于事务的分布式事务方案;
(2)基于业务的分布式事务方案。
其中,
(1)基于事务的分布式事务是将各个事务串联,并添加首先各个服务开启各自事务,然后执行CURD,将执行结果上报至统一事务管理器,统一事务管理器汇总各个事务结果,然后向各个事务发布提交或回滚的指令。
(2)基于业务的分布式事务在各自服务中维护完整的事务生命周期,与其他相关联的事务进行隔离,同时维护中间状态的数据,各个服务将各自的事务执行结果上报至统一事务管理器,统一事务管理器汇总各个事务结果,然后向各个服务发布提交或回滚的指令。
根据上述直到思想,出现了两种实际的方案:
两阶段提交和TCC。
2.1 两阶段提交(2PC,Two-phrase commit)
两阶段提交就是基于事务的分布式事务解决方案。
将分布式事务分成两个执行阶段:
(1)一阶段开启事务,执行操作;
(2)二阶段提交或回滚事务;
由统一事务管理器控制事务的执行。
2.1.1 一阶段
一阶段各个服务开启事务并执行相关的操作,将执行结果汇报给统一事务管理器,各个服务不会自动提交事务,只是上报执行结果。
一阶段执行示意图如下图所示,由图可知,
统一事务管理器接收到用户请求后,向各个本地事务管理器发送开启事务并执行CURD的指令,
在第一阶段,各个事务完成了除了提交的所有操作。
2.1.2 二阶段
二阶段统一事务管理器将各个服务事务的执行结果汇总,最终决定向各个事务发布提交或者回滚的指令;
(1)提交:全部服务事务执行结果均成功;
(2)回滚:任意一个服务事务出现失败;
提交
二阶段提交示意图如下图所示,由图可知,本地事务管理器将执行状态上报给统一事务管理器,
统一事务管理器综合处理后,给各个本地事务管理器发送指令,
当本地事务管理器的执行结果均成功时,统一事务管理器向各个本地事务管理器发送提交指令,
完成事务提交。
回滚
当任意一个本地事务管理器执行失败时,
统一事务管理器会向各个本地事务管理器发送回滚指令,
事务回滚。
2.1.3 存在的问题
(1)同步阻塞:当参与的事务使用公共资源时,其他事务参与者只能阻塞等待;
(2)单点故障:统一事务管理器出现故障时,整个系统不可用;
(3)数据不一致:二阶段,如果统一事务管理器只发送了提交指令,刚好网络异常,只有部分本地事务管理器接收到提交指令,另外一部分无法提交事务,数据不一致;
(4)不确定性:统一事务管理器发送提交指令后,部分本地事务管理器收到提交指令,刚好统一事务管理器和接收到提交指令的事务宕机,重新选举的统一事务管理器无法确定该消息是否提交成功。
2.2 TCC方案(Try-Confirm-Cancel)
TCC是基于业务的分布式事务方案。将完整的事务分成三个业务阶段独立维护执行:
Try-Confirm-Cancel。
其中,
Try:独立维护事务,原始数据CURD,同时操作预留数据,为后续提交或回滚做准备;
Confirm:独立维护事务,预留数据CURD,完成提交;
Cancel:独立维护事务,原始数据CURD,同时操作预留数据,完成回滚;
同样,需要一个统一事务管理器,基于业务的协调者,向各个独立的事务发布操作指令。
执行过程:
(1)提交:各个服务进入Try阶段,Try阶段全部执行成功,进入Confirm阶段,Confirm阶段全部执行成功:提交;
(2)回滚:各个服务进入Try阶段,Try阶段任意一个事务失败,进入Cancel阶段:回滚;
(3)回滚:各个服务进入Try阶段,Try阶段全部执行成功,进入Confirm阶段,Confirm阶段任意一个事务失败:回滚。
2.2.1 提交
TCC提交示意图如下图所示,由图可知,
基于业务的分布式事务,在各个服务中的各个阶段(Try,Confirm和Cancel),
维护自己的事务,执行完成后,将执行结果上报至统一事务管理器,
然后由统一事务管理器分发下一个阶段的指令。
(1)用户请求后,统一事务管理器将执行消息分发到各个服务,各个服务进入Try阶段,将Try阶段执行结果上报至统一事务管理器;
(2)统一事务管理器收集到Try阶段执行结果后,所有结果均是成功的,统一事务管理器向各个服务发送进入Confirm的指令,开始执行Confirm阶段的任务,各个服务将执行结果上报至统一事务管理器;
(3)统一事务管理器收集到Confirm阶段执行结果后,所有结果均是成功的,完成提交。
2.2.2 回滚
回滚则有两种情况:
(1)Try阶段异常:回滚;
(2)Confirm阶段异常:回滚;
Try阶段回滚
Try阶段回滚示意图如下图所示,由图可知,
(1)用户请求后,统一事务管理器将执行消息分发到各个服务,各个服务进入Try阶段,将Try阶段执行结果上报至统一事务管理器;
(2)统一事务管理器收集到Try阶段执行结果后,发现有Try异常,有Try正常,统一事务管理器向各个服务发送进入Cancel的指令,开始执行Cancel阶段的任务,完成回滚。
Confirm阶段回滚
Confirm阶段回滚示意图如下图所示,由图可知,
(1)用户请求后,统一事务管理器将执行消息分发到各个服务,各个服务进入Try阶段,将Try阶段执行结果上报至统一事务管理器;
(2)统一事务管理器收集到Try阶段执行结果后,所有结果均是成功的,统一事务管理器向各个服务发送进入Confirm的指令,开始执行Confirm阶段的任务,各个服务将执行结果上报至统一事务管理器;
(3)统一事务管理器收集到Confirm阶段执行结果后,有Confirm异常,有的Confirm正常,统一事务管理器向各个服务发送进入Cancel的指令,开始执行Cancel阶段的任务,完成回滚。
3 小结
(1)两阶段分布式事务方案基于事务(数据库层面)的分布式方案,TCC分布式事务方案基于业务的分布式方案;
(2)两阶段提交是强一致方案,但是仍有数据不一致的情况,统一事务管理器存在单点故障问题,导致整个系统不可用;
(3)TCC是基于业务的方案,在业务层面,业务侵入性大,实现复杂;
(4)提交:所有阶段均成功;回滚:任意阶段出现异常、失败等。
【参考文献】
[1]https://xiaomi-info.github.io/2020/01/02/distributed-transaction/
[2]https://zhuanlan.zhihu.com/p/183753774?utm_source=wechat_session
[3]https://blog.csdn.net/qq_45066628/article/details/119192658