分布式事务怎么理解?看这篇文章就够了!
在基于微服务框架的前提下大家是否对分布式事务有以下疑惑呢?
分布式事务框架是选择开源还是自研?
CAP原理什么是什么?
分布式事物为什么分为XA、TCC、SAGA?
满足什么标准才能用分布式事务?
在微服务独立数据源的思想,每一个微服务都有一个或者多个数据源,虽然单机单库事务已经非常成熟,但是由于网路延迟和不可靠的客观因素,分布式事务到现在也还没有成熟的方案,对于中大型网站,特别是涉及到交易的网站,一旦将服务拆分微服务,分布式事务一定是绕不开的一个组件,通常解决分布式事务问题。
CAP原理
我们了解分布式事务一定要了解业界出名的CAP原理,分别指可用性、一致性、分区耐受性;在分布式系统下CAP是一种客观存在的物理限制,暂时还没有办法突破,只能采取折中的方案;
一致性(Consistency):一致性是说,每次读取的数据都应该是最近写入的数据或者返回一个错误,而不是过期的数据,也就是说数据是一致的;
可用性(Availability):可用性是说,每次请求都应该得到一个响应,而不是返回一个错误或者失去响应,不过这个响应不需要保证数据是最近写入的,也就是说系统需要一直都是正常使用的,不会引起调用者异常,但并不保证响应的数据是最新的;
分区耐受性(Partition tolerance):分区耐受性是说,即使因为网络原因,部分服务器节点之间消息丢失或者延迟,系统依然应该是可以操作的;
当网络分区失效的时候,我们要么取消操作,这样数据就是一致性的,但是系统却不可用;MAME我们继续写入数据,但是数据的一致性就得不到保证;
对于一个分布式系统而言,网络失效一定会发生,也就是说,分区耐受性是必须要保证的,name在可用性和一致性上就必须二选一;
当网络分区失效,也就是网络不可用的时候,如果选择了一致性,系统就可能返回一个错误码或者干脆超时,即系统不可用,如果选择了可用性,那么系统总是返回一个数据,但是并不能保证这个数据是最新的。
ACID
不管是单机事务还是分布式事务一定要满足ACID原则。
原子性(Atomicity):要么全部发生,要么全部不发生,转化成代码语义,要么一起提交,要么一起回滚,不能存在中间状态的数据;
一致性(Consistency):数据始终处于合法状态,数据一定要对上,也就是不能部分提交;
隔离性(Isolation):并发操作的可见性,在事务发生的过程中,会有一个短暂的中间状态,隔离性表示其他的事务方来读取这个中间状态,隔离机制一般是通过锁实现的;
持久性(Durability):并更持久化,指数据提交了一定是要持久化的,即使数据库宕机,重启后还是会持久化;
XA协议
在传统的企业,解决分布式事务问题的传统方式是两阶段提交的方式 ,也称之为两阶段协议2PC/XA,他把分布式事务分解成两个执行阶段,如图:
在这个图示当中事务的参与方也叫资源管理者,可以是数据库或者消息队列;事务的协调方也称之为事务管理者,统一协调和管理两阶段事务。
两阶段执行步骤:
第一个阶段称之为准备阶段,也称之为投票阶段;事务管理者要求所有的资源管理者准备执行事务,然后每个资源管理者在本地执行事务,通过回复Ready表示就绪,可以提交或者是回滚;
第二个阶段在第一个阶段回复的过完成之后,事务管理者决策继续提交事务还是回滚事务,决策之后在要求所有的资源管理者去提交或者回滚事务;
为了统一标准,减少不必要的对接成本,有一个国家开发组织Open Group制定了分布式事务的XA规范,2PC应用场景少,要主要性能问题,要多次交互,还有实现复杂和死锁等问题,一般的中间件nosql、kafka、shardingsphere都不支持2PC协议,所以在互联网使用分布式事务的时候都会避免使用XA协议;
TCC协议
TCC协议在互联网金融行业应用比较广泛,TCC可以理解为2PC的一种变体,相遇于是应用层的2PC,TCC经常用于一些可以做资源预留的业务场景;TCC也有一个分布式事务协调者,统一事务的协调工作;工作原理如图所示:
服务需要实现三个接口Try、Confirm、Cancel接口;
业务应用通过分布式事务协调服务开启事务,分布式事务协调服务可以是外挂服务,也可以是业务应用本身;如果是外挂服务则需要考虑高可用;
业务应用分别调用服务的Try接口,执行事务操作,Try通常是一个预留资源的操作;
应用可以try返回的结果确定是提交还是回滚,分别调用Confirm和Canal接口;然后向事务协调者发送指定调用接口;
SAGA
SAGA模式一般要对业务场景进行建模,建模成一个状态机。
如果事务正常运行,那么事务的流程依次执行服务,状态机也会改变,最后到结束状态;
如果中间任何环节出了问题则会触发事务的补偿机制,事务补偿流程会反向依次执行补偿服务;
saga有两种做法一种协同是saga,系统是没有协调者,事务是通过参与方的相互发消息协作完成的;另外一种是编排是saga,事务过程中有一个集成的事务协调者,统一协调事务参与方完成事务
在整个事物执行的过程中数据是可能出现不一致的,这个时候如果有其他事务来读取和操作相关数据,就可能破坏数据的一致性,SAGA并不保证事务的隔离性;最简单的解决方式就是语义锁,阻塞或者拒绝其他事务。
微服务时代的事务处理原则
假定网关或者服务不可靠;
将全局事务建模成一组本地的ACID;
引入事务补偿机制处理失败的场景;
事务始终处于一种明确的状态(不管是失败还是成功);
最终一致;
考虑隔离性;
考虑幂等性;
异步响应式,尽量避免直接同步调用;
这些原则追求的是性能和扩展,而不是强一致性,第二点和第三点是SAGA事务模式的一个基础;SAGA事务模式是微服务时代推荐的处理分布式事务的一种方案;但是实现起来的门槛是比较高的,需要合理的状态建模,比如成功状态、补偿状态;再就是SAGA模式需要可靠的消息队列支持;最后一点是国内还没有比较成熟的支持SAGA模式的中间件;
说到这里我们应该可以自己判断开源组件是否满足业务需求,是使用开源分布式事务还是自研都有一定的基础准则;分布式事务并不是很难理解的东西,只是实现的机制比较难而已;