同一个项目 一个jar包 单个数据源
发生异常,下单、派单 都会回滚。
多个数据源
注意: 发生异常 只会回滚 下单操作,派单操作是单独的事物管理器,不会回滚
分布式事务产生的背景
在单体的项目中,多个不同业务逻辑都是在同一个数据源中实现事务管理,是不存在分布式事务的问题,因为同一数据源的情况下都是采用事务管理器,相当于每个事务管理器对应一个数据源
在单体的项目中,有多个不同的数据源,每个数据源中都有自己独立的事务管理器,互不影响,那么这时候也会存在多数据源事务管理:解决方案jta+ Atomikos
在分布式/微服务架构中,每个服务都有自己的本地的事务,每个服务本地事务互不影响,那么这时候也会存在分布式事务的问题。
实例演示
age = 0
订单数据回滚,但是派单数据无法回滚
事务的定义
对我们的业务逻辑可以实现提交或者回滚,保证数据的一致性的情况。
所以要么提交,要么回滚。
原子性a 要么提交 要么回滚
一致性c
隔离性i 多个事务在一起执行的时候,互不影响;
持久性d 事务一旦提交或者回滚后,不会在对该结果有任何影响
CAP理论
1.1 CAP定律#
这个定理的内容是指的是在一个分布式系统中、Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。
(一)一致性(C)
在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
(二)可用性(A)
在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
(三)分区容错性(P) 形成脑裂
问题
以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
https://baike.baidu.com/item/%E5%AE%B9%E9%94%99%E7%8E%87/9967698?fr=aladdin
zk保证数据一致性, cp
不保证可用性。
主所在 过半 能正常使用
2个机房 断开连接 主所在 没有过半 不能正常使用
Eureka 只要有一个可用,整个服务可用。ap 保证可用性
总结
以上可以知道分区容错性(P)主要代表网络波动产生的错误,这是不可避免的,且这个三个模式不可兼得,所以目前就只有两种模式:CP和AP模式。
其中CP表示遵循一致性原则,但不能保证高可用性,其中zookeeper作为注册中心就是采用CP模式,因为zookeeper有过半节点
不可以的话整个zookeeper将不可用。
AP表示遵循于可用性原则,例如Eureka
作为注册中心用的是AP模式,因为其为去中心化
,采用你中有我我中有你的相互注册方式,只要
集群中有一个节点可以使用
,整个eureka服务就是可用
的,但可能会出现短暂的数据不一致问题。
AP保证可用性
:但是不能保证每个副本数据数据一致性;
CP保证数据一致性
:如果有过半的zk节点宕机
的情况下,不
能保证可用
性,但是必须保证每个副本节点之间数据一致性, 比如ZK
;
Base理论
BASE是Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent(最终一致性)三个短语的缩写。BASE理论是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的总结, 是基于CAP定理逐步演化而来的。BASE理论的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。
(一)基本可用
基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性,注意,这绝不等价于系统不可用。
比如:响应时间上的损失。正常情况下,一个在线搜索引擎需要在0.5秒之内返回给用户相应的查询结果,但由于出现故障,查询结果的响应时间增加了1~2秒。
系统功能上的损失:正常情况下,在一个电子商务网站上进行购物的时候,消费者几乎能够顺利完成每一笔订单,但是在一些节日大促购物高峰的时候,由于消费者的购物行为激增,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级页面。
(二)软状态
软状态指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许
系统在不同节点的数据副本之间进行数据同步的过程存在延时
。
(三)最终一致性
最终一致性强调的是所有的数据副本,在经过一段时间的同步之后,最终都能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。
目前主流分布式解决框架
1.单体项目多数据源 可以jta+ Atomikos;
2.基于RabbitMQ的形式解决 最终一致性的思想;
3.基于RocketMQ解决分布式事务 采用事务消息;
4.LCN采用LCN模式 假关闭连接 (目前已经被淘汰) 官网已经无法访问;
5.Alibaba的Seata 背景非常强大,已经成为了主流;
以上适合于在微服务架构中,不适合于和外部接口
保证分布式事务问题。
6.跨语言
的方式实现解决分布式事务问题
类似于支付宝回调方式
LCN官网基本介绍
http://www.txlcn.org/zh-cn/ LCN
并不生产事务,LCN只是本地事务的协调工
现在官网已经不维护,可以参考:GitEE
https://gitee.com/wangliang1991/tx-lcn?_from=gitee_search
默认密码为
:codingapi
LCN基本实现原理
-
发起方与参与方都与我们的LCN管理器一直保持长连接;
-
发起方在调用接口之前,先向LCN管理器申请一个全局的事务分组id;
-
发起方调用接口的时候在请求头中传递事务分组id;
-
参与方获取到请求头中有事务分组的id的,则当前业务逻辑执行完实现假关闭,不会提交或者回滚当前的事务。
-
发起方调用完接口后,如果出现异常的情况下,在通知给事务协调者回滚事务,这时候事务协调则告诉给参与方回滚当前的事务。
-
发起方与参与方与我们的LCN管理器全局事务协调者一直保持长连接;
-
发起方在调用接口之前会使用Aop生成一个全局的事务分组id;
-
发起方在调用之后的时候会在请求头中传递该全局事务分组id;
-
参与方从请求头中获取该事务分组id,当前业务执行完毕之后不会提交该事务,则会使用假关闭。
-
发起方调用接口完之后,如果出现异常的情况下,会通知给协调者回滚该事务,协调者在通知给参与方实现回滚事务。
Lcn解决分布式事务的原理:
角色划分:
全局事务协调者
(组长);发起方
-----调用接口者参与方
----被别人调用接口
订单(发起方)调用派单(参与方)
1.发起方和参与方都会与我们的全局事务协调者保持长连接;
- 订单(发起方)连接到我们全局事务协调者,先
生成一个事务全局的分组id
- 当我们
发起方
调用接口的时候,会再请求头中
设置该事务全局分组id
; 参与方
从请求头中
获取到该全局分组id
,这是我们的数据源就不会提交。- 发起方调用参与方接口完毕之后,如果报错或者没有问题的情况下,都会发送
一个通知给事务协调者,通知给其他的参与方到底是回滚还是提交。
LCN实现分布式事务方案:
有可能会引发行锁
问题。
发起方生成全局id
Aop的重写的入口TransactionAspect
重新feign客户端拦截器 RequestInterceptor
思考
1. LCN底层如何判断自己是为发起方还是为参与方?
groupid会传递给参与方
2. 如何生成全局事务分组id的?
全局事务分组id 是本地生成好的,在发送给全局事务协调者
3. 如何将该全局事务分组id传递给参与方的?
RequestInterceptor拦截器设置在请求头中;
4. 如何实现数据源假关闭
的?
@LcnTransaction 生效
:经过aop
机制 TransactionAspect
类
AOP— 全局事务id创建缓存起来
执行目标方法—
Feign拦截器 ----
参与方获取全局id
1.SpringTracingApplier
拦截器 获取feign客户端请求头中的参数全局事务分组id,缓存到threadlocal中。
2. Aop的重写的入口TransactionAspect
3. 事务不会提交 暂时假关闭。
4. DataSourceAspect##LcnConnectionProxy
基于代理数据源的形式 直接重写了原生的了sql连接 注释掉 commit方法