Seata设计核心原理
创始人
2024-01-29 09:22:14
0次

Seata官网: Seata 官网

设计核心点

Seata中涉及三个角色

TC:  事务协调者,分布式事务的核心实现,Seata把它单独成一个服务器了

TM:  事务开启者,用来发起全局事务的,(其实也可以充当TC,只不过Seata进行隔离了)

RM: 资源管理器,每个单独事务的参与者

Seata支持多种模式

强一致性的模式

AT:也是Seata首推的模式,通过undo_log日志配合本地事务

XA:  利用数据库本身支持的分布式事务处理

最终一致性模式:

TCC:通过自己开发资源锁定,提交,回滚等接口

Saga:  长事务

全局事务和本地事务的区别

本地事务:一般都是数据库保证的,例如Mysql

全局事务:当有分布式事务时出现的一个概念,保证多个本地事务的正确执行

当有全局事务时,会有一个全局的xid标识,然后每个本地事务作为一个分支事务会有bid与唯一的xid进行绑定和关联

xid的处理

        每个分支事务都需要持有xid的数据,seata是基于以下几步做处理的

1,首先,TM事务先开启一个全局事务,然后获得一个Xid

2,获取Xid后当前的RM会把它放到 RootContext.bind(xid)中,其实就是一个ThreadLocal

3.   当调用其他微服务的时候通过SeataRestTemplateInterceptor拦截器拿取RootContext.getXID()获取xid然后往后面的微服务进行传输(该类实现了ClientHttpRequestInterceptor扩展点)

4.   其他微服务从SeataHandlerInterceptor中获取xid,然后又把它设置到自己的ThreadLocal中了,这样一来就实现了xid的往后传输了(该类实现了HandlerInterceptor扩展点

  以上便是seata对于xid扩展点的设计

AT模式的设计

        AT模式也是seata首推的模式,它通过undo_log日志和层层代理来对分布式事务进行处理,以下是它具体的流程

  1. 我们使用GlobalTransactional注解标记方法
  2. seata扫描该注解进行代理调用,有一个全局的GlobalTransaction接口,默认的实现类为DefaultGlobalTransaction
  3. 然后通过代理调用GlobalTransaction的begin开启全局事务方法,该方法会想TC发起一个开启全局事务的请求,然后TC返回一个xid
  4. 接着当前微服务按上面的流程处理xid
  5. 然后所有的微服务在调用commit提供本地事务时会被seata提供的ConnectionProxy进行代理,在调用commit方法,seata会先判断当前事务是否是全局事务(判断ThreadLocal中有没有XID数据),如果是的话会根据sql语句进行前置镜像的保存,然后执行sql,接着保存后置镜像,然后会向TC注册一个分支事务,如果本地事务提交失败还会发送一个报告给TC
  6. 如果每个分支事务都执行成功了那么TC后台会有个定时器查询全局事务的分布事务,如果全部都提交成功的话,那么就会循环所有分支事务然后由TC调用RM的branchCommit方法,如果有一个失败的话就会调用branchRollback方法
  7. 以上便是大概的交互流程,如果要看详细的话可能要去看源码才知道了

AT模式的优势

  •  不需要持有connection的连接了,会提升数据库的性能
  •  TC单节点问题可以通过部署多台来解决
  •  分支事务的二阶段提交有了相应的校验保证能执行完成

Seata的全局锁

        分支事务在注册的时候是需要在TC那边获取一把全局锁的,TC的全局锁其实就是往数据表插入一个xidkey的字段,该字段是唯一性,同时只能有一个全局事务持有

 全局锁的作用

        写隔离:因为AT模式下第一阶段本地事务其实已经提交了,所以本地事务读到的数据已经是更改后的了,如果此时有其他全局事务读到了该数据,实际上是等于读到了未提交的数据,那么就有可能会出现脏读的问题,所以seata才会设计全局锁来解决这个问题,此时如果有其他全局事务要去更改这个数据,它实际上是拿不到锁的,所以就会阻塞在那里,直到上面的全局事务执行完成才能获取到数据

        读隔离:用 for update 配合 GlobalLock注解seata帮我们实现了读隔离,当一个方法标记了GlobalLock后,那么有另一个GlobalLock方法要去读同一个数据,也会被阻塞那里,等到前面持有锁的线程释放锁以后就会获取到了

总结

        seata核心的要求就是TC,还有就是对于分布式事务的一个设计方案,然后就是seata大量使用了代理来处理逻辑,这个也是比较值得我们借鉴的,另一个值得借鉴的就是使用ThreadLocal加上其他扩展点实现了xid的传输

        对于我自己来说也是这样,如何把学到的知识用文字表达出来也是比较考验我自己的,以后也会慢慢加强这方面的能力

上一篇:Java文件读写数据流

下一篇:Re-Ranking

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...