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

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
群晖外网访问终极解决方法:IP... 写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法&#x...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
Azure构建流程(Power... 这可能是由于配置错误导致的问题。请检查构建流程任务中的“发布构建制品”步骤,确保正确配置了“Arti...