Seata原理!

Seata和LCN的区别

 

1. 基本实现思路是一样的,唯一区别在于回滚方式,LCN采用代理数据源假关闭连接,暂时不提交本地事务(不提交也不回滚),但是容易造成死锁。

   -- 假关闭其实就是api,因为连接也是可以被aop代理的,原生的commit被拦截到就不会走commit会进行wait线程等待,等待全局事务协调者发送通知是提交还是回滚。

2. seata采用undo_log的形式逆向生成sql语句实现回滚。

lcn存在问题:容易死锁。

例如:事务协调者宕机,无法通知参与方是提交还是回滚,所以线程会一直被占用(死锁)。

undo_log日志逆向回滚

伪代码:

1  @RequestMapping("/insertUser")
2  @GlobalTransactional
3  public String insertUser(){
4    // 第一步.添加姓名到user表;
5    int i = userMapper.insertName(“王明”);
6  
7    // 第二步.调用会员服务修改姓名为王敏;
8    int result = rpcUrl.putName("王敏"); 
9     
10   // 模拟报错
11   int a = 1 / 0;  
12 }

使用@GlobalTransactional注解开启事务,

执行完第5行后数据就会提交到user表;

第8行会员服务同样会落实到数据库;

执行到第11行报错后会通过undo_log表逆向回滚数据;

 - undo_log表中的rollback_info字段以二进制方式记录着新增的语句,通过该字段进行逆向回滚。

Seata四种模式

Seata AT 模式

默认AT模式(逆向sql)

AT 模式是无侵入的分布式事务解决方案,适用于不希望对业务进行改造的场景,几乎0学习成本。

TCC 模式对代码侵入比较高,是高性能分布式事务解决方案,适用于核心系统等对性能有很高要求的场景。

其余两种使用的不多。

Seata原理分析

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

笔记!

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日志表

如何逆向实现sql语句:

 insert 逆向 delete

 delete逆向insert

 update逆向肯定是update

前置镜像和后置镜像sql演示:

select * from orderId=1    得到state=0 ----前置镜像

update order set state(1) where orderId=1    原生sql语句

select * from orderId=1    得到state=1 ----后置镜像

回滚(记录到undo_log):

Update order set state(0) where orderId=1  ---还原

逆向sql流执行程

1.业务逻辑sql:

update product set name = '222' where name = 'TXC';

  1.1解析 SQL:得到 SQL 的类型(UPDATE),表(product),条件(where name = 'TXC')等相关的信息。

  1.2查询前镜像:根据解析得到的条件信息,生成查询语句,定位数据。

2.前置镜像:

select id, name from product where name = 'TXC';      // 得到:id=1, name=111

3.执行业务逻辑 SQL:

更新这条记录的 name 为 '222'

4.查询后镜像:根据前镜像的结果,通过 id主键 定位数据

select id, name from product where id = 1;

5.回滚的语句:根据前镜像和业务 SQL 的相关信息生成并执行

update product set name = '111' where id = 1;

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

祁_z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值