这里我们一起来学习下分布式事务,大概有以下几个学习内容:
1、分布式事务产生的背景
2、解决分布式事务基本思想Base和CAP理论
3、柔性事务与刚性事务区别
4、理解分布式事务核心思想软状态和最终一致性思想
5、分布式事务常见解决方案
5.1 传统模式使用Jta+Atomikos
5.2 2PC与3PC实现的区别
5.3 使用阿里巴巴TCC补偿框架(用于Dubbo)
5.4 使用可靠消息模式
5.5 使用LCN框架解决分布式事务
5.6 阿里GTS框架解决分布式事务
分布式事务产生的背景
在微服务环境下,因为会根据不同的业务会拆分成不同的服务,比如会员服务、订单服务、商品服务等,让专业的人专业的事情,每个服务都有自己独立的数据库,并且是独立运行,互不影响。
服务与服务之间通讯采用RPC远程调用技术,但是每个服务中都有自己独立的数据源,即自己独立的本地事务。两个服务相互通讯的时候,两个本地事务互不影响,从而出现分布式事务产生的原因。
传统项目大部分情况下,不会产生分布式事务,但是在项目中如果采用多数据源方式,就会出现分布式事务。还有另外一种就是不同业务拆分成不同服务,不同服务有自己的独立数据库,这种也需要分布式事务。
本地事务有效范围在同一个jdbc里面,不同jdbc,事务是隔离的。同一个数据库,不同jdbc,事务也是隔离的。
截图里的场景是两个微服务,一个是下单,一个是扣库存。如果这两个服务调用完,出现int i=1/0;出现程序错误。这种就需要分布式事务了。
如果是在两个微服务的内部处理逻辑,出现程序出错,比如下面,在扣库存的服务里,int i=1/0;出现异常。这种就不是分布式事务异常。这种情况,完全可以等库存服务返回状态码,判断对错,如果错误,就手动回滚事务。
ACID酸碱平衡理论
需要理解一些名词,CAP与Base理论、柔性事务与刚性事务、理解最终一致性思想、JTA+XA、两阶段与三阶段提交
CAP:帽子原理
CAP定律
这个定理的内容是指的是在一个分布式系统中、Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。
一致性(C)
在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
可用性(A)
在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
分区容错性(P)
以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
Base理论
BASE理论
BASE是Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent(最终一致性)三个短语的缩写。BASE理论是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的总结, 是基于CAP定理逐步演化而来的。BASE理论的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。
基本可用
基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性----注意,这绝不等价于系统不可用。比如:
(1)响应时间上的损失。正常情况下,一个在线搜索引擎需要在0.5秒之内返回给用户相应的查询结果,但由于出现故障,查询结果的响应时间增加了1~2秒
(2)系统功能上的损失:正常情况下,在一个电子商务网站上进行购物的时候,消费者几乎能够顺利完成每一笔订单,但是在一些节日大促购物高峰的时候,由于消费者的购物行为激增,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级页面
最终一致性
最终一致性强调的是所有的数据副本,在经过一段时间的同步之后,最终都能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。
软状态
软状态指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时
软状态案例就是支付,平台调用支付宝或者微信支付接口后,会重定向到同步地址,并且支付宝/微信支付会采用HttpClient,消息通知异步地址。这种情况下平台和支付宝就是两个微服务,异步通知可以不用马上通知,但是最终是要通知给平台,让平台处理这笔订单。如果异步通知失败的情况下(异常或者通知接口出现延迟),支付宝会自动重试,重试过程中,会每隔一定时间(具体时间我也忘记了),补发异步通知,这个补发通知过程就是补偿机制。或者平台可以调用支付宝接口,查询支付状态。这种方式,平台和支付宝,可能是不同开发语言的,这种可以用补偿机制。但是分布式事务是不能跨语言的。
幂等性
一次和多次请求某一个资源对于资源本身应该具有同样的结果(网络超时等问题除外)。也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同。
这里需要关注几个重点:
- 幂等不仅仅只是一次(或多次)请求对资源没有副作用(比如查询数据库操作,没有增删改,因此没有对数据库有任何影响)。
- 幂等还包括第一次请求的时候对资源产生了副作用,但是以后的多次请求都不会再对资源产生副作用。
- 幂等关注的是以后的多次请求是否对资源产生的副作用,而不关注结果。
- 网络超时等问题,不是幂等的讨论范围。
幂等性是系统服务对外一种承诺(而不是实现),承诺只要调用接口成功,外部多次调用对系统的影响是一致的。声明为幂等的服务会认为外部调用失败是常态,并且失败之后必然会有重试。
什么情况下需要幂等
业务开发中,经常会遇到重复提交的情况,无论是由于网络问题无法收到请求结果而重新发起请求,或是前端的操作抖动而造成重复提交情况。 在交易系统,支付系统这种重复提交造成的问题有尤其明显,比如:
- 用户在APP上连续点击了多次提交订单,后台应该只产生一个订单;
- 向支付宝发起支付请求,由于网络问题或系统BUG重发,支付宝应该只扣一次钱。 很显然,声明幂等的服务认为,外部调用者会存在多次调用的情况,为了防止外部多次调用对系统数据状态的发生多次改变,将服务设计成幂等性
柔性事务和刚性事务
两阶段提交协议
三段提交协议
两段和三段提交的区别
SpringCloud结合LCN的几个实例,我还没总结,这里放几个demo
https://blog.csdn.net/fuck487/article/details/79937066
codingapi官方文档:http://www.txlcn.org/zh-cn/docs/preface.html
LCN是这三个的首字母命名的:
锁定事务单元(lock)
确认事务模块状态(confirm)
通知事务(notify)
5.0以后由于框架兼容了LCN、TCC、TXC三种事务模式,为了避免区分LCN模式,特此将LCN分布式事务改名为TX-LCN分布式事务框架。
框架定位
LCN并不生产事务,LCN只是本地事务的协调工
TX-LCN定位于一款事务协调性框架,框架其本身并不操作事务,而是基于对事务的协调从而达到事务一致性的效果。
解决方案
在一个分布式系统下存在多个模块协调来完成一次业务。那么就存在一次业务事务下可能横跨多种数据源节点的可能。TX-LCN将可以解决这样的问题。
例如存在服务模块A 、B、 C。A模块是mysql作为数据源的服务,B模块是基于redis作为数据源的服务,C模块是基于mongo作为数据源的服务。若需要解决他们的事务一致性就需要针对不同的节点采用不同的方案,并且统一协调完成分布式事务的处理。
方案:
若采用TX-LCN分布式事务框架,则可以将A模块采用LCN模式、B/C采用TCC模式就能完美解决。
TX-LCN 主要有两个模块,Tx-Client(TC) Tx-Manager(TM). TC作为微服务下的依赖,TM是独立的服务。
TC开启分布式事务注解
在主类上使用
@EnableDistributedTransaction
@SpringBootApplication
@EnableDistributedTransaction
public class DemoAApplication {
public static void main(String[] args) {
SpringApplication.run(DemoDubboClientApplication.class, args);
}
}
TC微服务A业务方法配置
@Service
public class ServiceA {
@Autowired
private ValueDao valueDao; //本地db操作
@Autowired
private ServiceB serviceB;//远程B模块业务
@LcnTransaction //分布式事务注解
@Transactional //本地事务注解
public String execute(String value) throws BusinessException {
// step1. call remote service B
String result = serviceB.rpc(value); // (1)
// step2. local store operate. DTX commit if save success, rollback if not.
valueDao.save(value); // (2)
valueDao.saveBackup(value); // (3)
return result + " > " + "ok-A";
}
}
TC微服务B业务方法配置
@Service
public class ServiceB {
@Autowired
private ValueDao valueDao; //本地db操作
@LcnTransaction //分布式事务注解
@Transactional //本地事务注解
public String rpc(String value) throws BusinessException {
valueDao.save(value); // (4)
valueDao.saveBackup(value); // (5)
return "ok-B";
}
}
TC配置信息说明
# 默认之配置为TM的本机默认端口
tx-lcn.client.manager-address=127.0.0.1:8070
事务控制原理
TX-LCN由两大模块组成, TxClient、TxManager,TxClient作为模块的依赖框架,提供TX-LCN的标准支持,TxManager作为分布式事务的控制放。事务发起方或者参与反都由TxClient端来控制。
原理图:
核心步骤
-
创建事务组
是指在事务发起方开始执行业务代码之前先调用TxManager创建事务组对象,然后拿到事务标示GroupId的过程。
-
加入事务组
添加事务组是指参与方在执行完业务方法以后,将该模块的事务信息通知给TxManager的操作。
-
通知事务组
是指在发起方执行完业务代码以后,将发起方执行结果状态通知给TxManager,TxManager将根据事务最终状态和事务组的信息来通知相应的参与模块提交或回滚事务,并返回结果给事务发起方。