文章目录
自从我接触分布式系统以来,困扰我的最大两件事,第一是业务拆分,第二个就是分布式事务的问题。在做单体应用的时候,我们只处理一个库的数据,一个@Transaction注解就能搞定。而在分布式系统中,随着业务服务的拆分,数据库自然而然的也会拆分,所以原本的单库事务就变成了多个数据库的事务操作,所以我们就要想尽各种办法去保证数据的一致性。
通过重新梳理分布式事务的知识,我总结了两理论、一模型、两协议、三方案。
基本特性
就是我们常说的ACID特性,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
- 原子性(Atomicity),要么都执行、要么都不执行
- 一致性(Consistency) ,事务执行前后数据保持一致
- 隔离性(Isolation),一个事务的内部操作对数据状态的修改不影响其他事务
- 持久性(Durability),事务完成后,数据的状态会持久化到磁盘
两理论
CAP理论
CAP理论指的是分布式系统中不能同时满足一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)这三个基本需求,最多同时满足两个。
一致性(Consistency)
可用性(Availability)
分区容错性(Partition tolerance)
BASE理论
BASE理论是由CAP理论扩充而来,因为CAP中只能同时支持两个特性,所以出现了BASE理论。BASE理论有如下三个特性:
基本可用(Basically Available)
软状态(Soft State)
最终一致性(Eventually Consistent)
一模型
DTP模型(X/Open Distributed Transaction Processing)
应用程序(AP)
资源管理器(RM)
事务管理器(TM)
XA协议标准
两协议
二阶段提交协议(2PC,Two Phase Commitment Protocol)
- 准备阶段
事务管理器TM通知资源管理器RM准备分支事务,记录事务日志,并返回准备结果。 - 提交/回滚阶段
所有的资源管理器准备完成,TM向所有的RM发起提交。反之则发起回滚。
规则
提交条件,RM都返回“准备好”TM才会发起提交;
回滚条件,RM有一个返回“未准备好”TM就会发起回滚;
所有RM在第一阶段都能正常响应,那么TM在第二阶段发送提交或者回滚就一定能成功;
优点
简单易行
缺点
- 同步调用,容易发生资源锁定
- 强一致性,任何一个RM失败都会导致回滚
- TM在第二阶段出现故障,那么RM会被一直锁定
- 局部网络异常,部分RM未执行提交,会导致数据不一致
三阶段提交协议
基于二阶段提交协议出现的问题,三阶段提交协议 应运而生。
- 询问阶段
询问是否可以执行事务操作,只是询问不做事务处理,此阶段添加了超时中止处理 - 准备阶段
询问阶段所有的RM都返回成功,那么TM开始向所有RM发起准备请求,RM执行事务处理,但不提交 - 提交/回滚阶段
在准备阶段所有的RM返回成功,那么TM开始向所有RM发起提交请求,RM执行事务提交处理,否则回滚
优点
引入了超时机制,解决了2PC阶段的资源锁定问题
缺点
- 相对2PC多了询问的阶段
- 仍然存在数据不一致性的问题
三方案
TCC事务解决方案
TCC是一种柔性事务解决方案,TCC将事务提交分为Try-Confirm-Cancel三个操作。
- Try
预留业务资源/数据校验 - Confirm
确认提交业务操作 - Cancel
取消业务操作
举例:存在一个下单事务,需要库存和订单两个服务,每个服务单独对应不同的数据库,流程示意如下图所示:
Confirm和Cancel接口都必须满足幂等性设计
两个服务的Try都执行成功才执行Confirm
部分服务的Try执行失败就执行Cancel
消息中间件方案
主要是利用消息中间件的可靠性机制来实现数据一致性的投递,对于一些数据一致性实时性要求不高的场景,一般可以采取这种方案。
举例:业务中调用支付的场景,第三方支付异步结果返回后我们才进行账户的相关逻辑处理,比如积分处理,处理流程如下:
最大努力通知型方案
该方案和基于可靠性消息投递最终一致性方案类似,简单来说就是在第三方支付异步返回结果的基础上,第三方支付主动提供一个支付结果查询的接口,也是适用于对数据一致性实时性不高的场景。