面试问到Seata看这一篇就够了

一、分布式事务产生的背景

1.在单体的项目中,多个不同业务逻辑都是在同一个数据源中实现事务管理,是不存在分布式事务的问题,因为同一数据源的情况下都是采用事务管理器,相当于每个事务管理器对应一个数据源。

2.在单体的项目中,有多个不同的数据源,每个数据源中都有自己独立的事务管理器,互不影响,那么这时候也会存在多数据源事务管理:解决方案jta+ atominc

3.在分布式/微服务架构中,每个服务都有自己的本地的事务,每个服务本地事务互不影响,那么这时候也会存在分布式事务的问题。

单体项目中不存在事务问题
同一个数据源,用的同一个事务管理器

事务传播行为

每个数据源都有自己独立的事务管理器,事务管理器之间互不影响

采用rpc远程通讯,跨jvm,也存在分布式事务问题,为什么?
生产者调用完接口后,突然抛出异常,就存在事务问题,
如果还没调用接口就抛出异常,那就不存在分布式事务问题了
必须要抛出异常就会回顾和
如果接口调用失败就不存在分布式事务问题,因为调用方会根据返回结果去手动回滚事务

问题:
1、分布式项目中,使用同一个数据源,会存在分布式事务问题吗?

2、数据源和数据库的区别?

二、分布式事务的六种解决方案

三、Base和CAP理论

传统事务ACID最终效果就是强一致性
A原子性:要么回滚要么提交,
C一致性:
I隔离性:多个事务之间互不影响
D持久性:事务提交之后不会再对数据改变
Base理论:Base理论是对CAP理论中一致性(c)和可用性(a)权衡的结果,来源于对大规模互联网系统分布式实践的总结,是基于CAP理论演化而来的。
核心思想:保证数据最终一致性
ba:基本可用,在分布式系统出现不可预知的故障时候,允许损失部分可用性,比如响应时间延长
s:软状态
e:最终一致性

为什么分布式系统中不可能存在强一致性?zk不久是强一致性的吗?

CAP理论:
P,专线,异地通讯使用专线比较安全,相当于私网(内网?)
分区容错性:服务器能容忍网络通讯出现故障,无法避免的

Begin,上行锁,其他线程不能够对改行数据做操作
调用数据库
Commit/rollback,解行锁

Redis中没有行锁,其他线程也可以同时操作同一个key

四、目前主流分布式事务解决框架

1.单体项目多数据源 可以jta+ Atomikos
2.基于rabbitmq的形式解决 最终一致性的思想
3.基于rocketmq解决分布式事务 采用事务消息
4.LCN采用lcn模式 假关闭连接 (目前已经被淘汰)
5.Alibaba的Seata 未来可能是主流 背景非常强大

kafka不行吗?
tcc/2pc/最终一致性
zk是先提交再同步

为什么所有的请求要交给主写,再同步
保持数据一致性

参与者和协调者
3PC就是在2PC上多加了一次询问
为什么多加?
保证连接可靠

五、fallback与blockHandler的区别

fallback是服务熔断或者业务逻辑出现异常执行的方法(1.6版本以上)
blockHandler 限流出现错误执行的方法。

六、TX-LCN分布式事务框架

LCN不生产事务,LCN只是本地事务的搬运工

使用简单,接口和实现方法加个注解就好了,每个服务都连接到lcn

LCN到5
seata到1

LCN实现分布式事务三种方案(模式):LCN模式、TCC模式、TXC模式

LCN是协调者
发起方
参与方

七、LCN基本实现原理

1.发起方与参与方都与我们的LCN管理器一直保持长连接;
2.发起方在调用接口之前,先向LCN管理器申请一个全局的事务分组id;
3.发起方调用接口的时候在请求头中传递事务分组id;
4.参与方获取到请求头中有事务分组的id的,则当前业务逻辑执行完实现假关闭,不会提交或者回滚当前的事务。
5.发起方调用完接口后,如果出现异常的情况下,在通知给事务协调者回滚事务,这时候事务协调则告诉给参与方回滚当前的事务。

八、Seata解决分布式事务问题

九、Seata与LCN的区别

Seata没有管理页面
seata原理和LCN差不多

易于使用,高性能的开源分布式事务解决框架

阿里云GTS 是收费的分布式事务解决框架,商业版,延迟短、性能好
学的是0.9版本
四种模式
AT几乎等于LCN模式
TCC
SAGA
XA

Seata有三个组成部分:
事务协调器TC:协调
事务管理器TM:发起方
资源管理器RM:参与方

只要写网络通讯框架就要用到netty

十、Seata实现原理

1.TM(发起方)连接到我们的TC事务协调者,创建一个全局的事务的xid,保存到ThreadLoacl中;
2.TM(发起方)和RM(参与方)都被Seata的数据数据源实现代理,在原生的sql之前和之后保存原来和修改后日志到undo_log中,方便后期实现回滚。
3.TM(发起方)使feign客户端调用接口时候,在ThreadLoacl中获取xid,设置到请求头中;
4.RM(参与方)从请求中获取到该xid,设置到ThreadLoacl中,同时也会向seataserver注册该分支事务。
5.TM(发起方)将当前本地事务的结果,告诉给协调者TC,协调者TC在通知所有的分支是否回滚。
6. TM(发起方)如果调用接口成功之后抛出异常的情况下,告诉给协调者TC,协调者TC在通知所有的分支根据根据全局的xid和分支事务的id 查询分支数据源的undo_log日志表逆向生成sql语句实现回滚,同时删除对应的undo_log日志
7. TM(发起方)如果调用接口成功之后没有抛出任何的异常,告诉给协调者TC,协调者TC在通知所有的分支根据根据全局的xid和分支事务的id 查询分支数据源的 删除对应的undo_log日志表

Seata原理分析
1.发起方TM会向我们的TC协调者申请一个全局的事务id,保存到threadlocal中;
2.TM和RM都会被Seata代理数据源,写入原来和修改后内容保存到undo_log表中;
3.TM从请求头中传递该全局的事务id给RM,RM从请求中头中获取到该全局事务id,并且注册该分支。
4.如果TM调用接口成功之后,如果报错的情况下则通知给协调者,协调者在告诉所有的分支都开始回滚,直接根据本地事务id+xid查询undo_log表 ,逆向生成sql语句回滚,同时删除该undo_log日志。
5.如果TM调用接口成功之后,如果没有报错的情况下则通知给协调者,协调者在告诉所有的分支都开始提交事务,直接根据本地事务id+xid删除对应的undo_log表记录即可。

注意:前置镜像和后置镜像的作用

undo_log表每个数据库都要

前置镜像 select * from order state = 0 原来的值
Update order set state(1) where userID=1 订单服务实现 1
后置镜像 1 之后的值
逆向的话 Update order set state(0) where userID=1

要注册到nacos上

seata会插入
优点:避免死锁,在发起方突然宕机的情况下,参与方收不到解锁消息就会死锁
缺点:脏读

十一、springboot整合seata

第一步:引入依赖
第二步:bin下的file文件和registry文件放入到每个项目中,并修改,分组名称要保持一致
第三步:yml配置seata
第四步:引入DataSourceProxy配置文件

十二、

threadlocal:value值,当前线程为key
代理

全局事务id-xid
本地事务id
前置镜像:sql操作前的情况
后置镜像:sql操作后的情况

超时也会自动回滚

多个线程同时修改,有行锁
行锁是数据库自带的吗?

十三、Seata与Lcn的区别

1.基本实现的思路是一样的,唯一区别在于回滚的方式 LCN采用代理数据源假关闭连接,暂时不提交本地事务,但是容易造成数据的死锁。
2.Seata采用undo_log的形式逆向生成sql语句实现回滚,避免死锁现象但是容易出现脏读。

十四、

十五、

十六、

十七、

十八、

十九、

二十、

二十一、

二十二、

二十三、

二十四、

二十五、

二十六、

二十七、

二十八、

二十九、

三十、

发布了52 篇原创文章 · 获赞 2 · 访问量 1861

猜你喜欢

转载自blog.csdn.net/qq_42972645/article/details/104804474