数据库事务特性包括原子性(Atomicity )、一致性( Consistency )、隔离性或独立性( Isolation)和持久性(Durabilily)。以下单为例,在单体的电商系统中,调用下单服务,整个服务操作在同一事务中完成。下单成功以后,扣减库存,生成订单操作会同时生效,数据都会写入库存数据库,订单数据库。流程如下:
在分布式系统中,如果只是将下单服务进行微服务化,即将下单服务拆分为调用订单服务API和商品服务API。微服务拆分后,订单服务API对应独立的订单数据库,商品服务API对应独立的商品数据库。如果,直接按照单体服务中的的流程,只是将原来的本地方法替换微服务API的话,其流程图如下:
在下单服务中,使用RPC或者HTTP请求调用商品服务API和订单服务API,类似client(客户端)调用server(服务器)方式。此时,如果出现如下两个问题:
流程图如下:
因为,如上两个原因,会造成商品与订单数据的数据状态不一致,情况如下:
如何解决直接拆分为微服务后,数据状态不一致的问题呢?这时,就需要引入分布式事务了。
首先,会想到通过数据库的两阶段提交(2PC)方式实现分布式事务。根据CAP理论(详细可以参考深入理解CAP理论和适用场景),2PC属于CP模式。该协议分为以下两个阶段:
两阶段提交流程正常的执行流程,如下:
这种方式操作简单,通俗易懂,该中方式也有如下几个缺点:
以上,两种情况会导致部分数据提交成功,部分提交失败,造成数据不一致。操作流程如图:
TX-LCN分布式事务框架(LCN事务模式),基于2PC协议实现的分布式事务解决方案。TX-LCN由TxClient事务发起方、TxManager事务协调者组成。执行步骤如下:
创建事务组,事务发起方开始执行业务代码之前先调用TxManager创建事务组对象,然后拿到事务标示GroupId的过程。
加入事务组,事务参与方在执行完业务方法以后,将该模块的事务信息通知给TxManager的操作。
通知事务组,事务发起方执行完业务代码以后,将发起方执行结果状态通知给TxManager,TxManager将根据事务最终状态和事务组的信息来通知相应的参与模块提交或回滚事务,并返回结果给事务发起方。
如上的操作过程如图:
优劣势分析
优势:TxManager作为分布式服务,实现了事务协调者的角色,如果集群部署,避免了事务协调者单点故障的问题。
劣势:事务参与者的同步阻塞问题,长事务,数据不一致没有解决。
TCC模式,该种模式也类似与两阶段提交方式,总共由三个步骤,分成 Try,Confirm / Cancel 两个阶段,try阶段执行成功,则执行Confirm阶段,反之则执行Cancel阶段。三个阶段的操作内容如下:
操作流程如下:
TCC模式的实现具体方案包括:
优劣势分析
优势:三个阶段的事务单独控制,避免了2PC中所有事务参与者同步阻塞的问题。对于三个阶段实现容错机制,如果在三个阶段中执行发生异常(网络超时,乐观锁异常等等),每个阶段都会对执行的操作进行重试,所以,TCC三个阶段逻辑要保证幂等性。TCC模式也属于数据强一致模式,适用于金融行业对数据一致性要求比较高的情景。
劣势:该模式对代码的嵌入性高,要求每个业务需要写三种步骤的操作,并且,数据一致性控制几乎完全由开发者控制,对业务开发难度要求高。在confirm和cancel阶段,如果重试以后还是抛出异常,则会造成数据不一致。
在分布式系统中,一般更加重视系统的可用性,分布式事务解决方案都基于BASE理论,它是用来对CAP定理进行进一步扩充的。BASE理论指的是:
BASE理论是对CAP中的一致性和可用性进行一个权衡的结果,理论的核心思想就是:我们无法做到强一致,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。
消息中间件+HttpClient实现分布式事务,实现的思路如下:
执行流程如图:
优劣势分析
优势:适用于两个步骤有一定间隔时间的场景,例如,用户输入密码付款,对智能硬件的指令控制等场景。
劣势:如果回调服务出现异常,重试也无法解决,则此时,就会出现数据不一致的情况。