首页 > 编程语言 >Seata 1.5.2 源码学习(Client端)

Seata 1.5.2 源码学习(Client端)

时间:2022-11-18 18:58:14浏览次数:45  
标签:1.5 事务 请求 TC Client RM 执行 源码 TM

在上一篇中通过阅读Seata服务端的代码,我们了解到TC是如何处理来自客户端的请求的,今天这一篇一起来了解一下客户端是如何处理TC发过来的请求的。要想搞清楚这一点,还得从GlobalTransactionScanner说起。

启动的时候,会调用GlobalTransactionScanner#initClient()方法,在initClient()中初始化TM和RM

TM初始化,主要是注册各种处理器,最终构造一个处理器映射表,不再多说

HashMap<Integer/*MessageType*/, Pair<RemotingProcessor, ExecutorService>> processorTable = new HashMap<>(32);

重点关注RM初始化

RM初始化过程中,设置了 resourceManager 和 transactionMessageHandler,然后也是注册各种处理器,最终也是构造一个消息类型和对应的处理器的一个映射关系

可以看到,图中上半部分是RM特有的,下半部分与TM初始化注册处理器类似

然鹅,真正处理请求的还是靠调用各个处理器中的handler.onRequest()方法,于是问题的关键就很明显了,就在于handler

1.  ResourceManager

在了解ResourceManager之前,让我们首先了解一下ResourceManagerInbound和ResourceManagerOutbound

ResourceManagerInbound是处理接收到TC的请求的,是TC向RM发请求

ResourceManagerOutbound是处理流出的消息的,是RM向TC发请求

ResourceManager继承了二者,所以既负责向TC发请求,又负责接收从TC来的请求。

还记得刚才在RMClient中是怎么获取ResourceManager的吗?是调用DefaultResourceManager.get()获取的

DefaultResourceManager.get()得到的是一个单例DefaultResourceManager,创建DefaultResourceManager的时候会构建一个分支类型与ResourceManager的一个Map

2. TransactionMessageHandler

TransactionMessageHandler负责处理接收到的RPC消息

前面在 RMClient 中通过 DefaultRMHandler.get() 获取 TransactionMessageHandler

3. 消息处理

RMClient#init()的时候new了一个RmNettyRemotingClient

这里要记住,rmNettyRemotingClient的两个成员变量此时已经被赋值了:

  • resourceManager是DefaultResourceManager,
  • transactionMessageHandler是DefaultRMHandler

RmNettyRemotingClient构造方法中调用父类AbstractNettyRemotingClient的构造方法

可以看到,根据收到的RPC消息类型,从processorTable中获取对应的Processor,最后调用对应RemotingProcessor的process()方法进行处理消息

RemotingProcessor的实现类很多,挑其中一个RmBranchCommitProcessor看一下

真相大白,最终还是调DefaultRMHandler#handle()

捋一下这个过程

最后,补充一个,this为什么是DefaultRMHandler

补充二:AbstractTransactionRequestToRM

4. 分支事务提交(二阶段)

交给AsyncWorker去执行

可以看到:

  1. 封装成一个Phase2Context对象,并将其放入队列中
  2. 如果放入成功,则立即返回提交成功,后续交由定时任务执行
  3. 如果放入失败,则主动触发定时任务先执行一次,以便腾出空间来,待执行完后,队列里面就有空间了,再将任务放入队列,等待下一次定时任务执行
  4. 定时任务1秒执行一次,执行的时候将队列中的任务取出,然后循环遍历分段执行
  5. 执行的过程就是删除对应事务的undo log
  6. 如果过程中抛异常,则将任务再放回队列中

所以,RM收到TC发的提交指令后,仅仅只是删除该事务的undo_log表记录

5. 分支事务回滚(二阶段)

与提交类似

所以,回滚就是根据事务的undo_log进行回滚

6. 总结

1、启动时,自动代理数据源,应用GlobalTransactionalInterceptor,初始化TM和RM

2、进入@GlobalTransactional业务方法时,TM向TC发请求申请开启全局事务,并获得全局事务ID

3、业务方法调用远程服务接口完成业务处理

4、RM执行本地逻辑,注册分支事务,获取全局锁,成功后提交本地事务并写入undo_log,本地事务提交成功后向TC报告分支事务

5、TM发起全局事务提交请求,TC向所有已注册的RM发请求,让RM进行分支提交,删除本地undo_log

6、若执行失败,TM发起全局事务回滚,TC向所有RM发请求,回滚分支事务,还原数据

 

标签:1.5,事务,请求,TC,Client,RM,执行,源码,TM
From: https://www.cnblogs.com/cjsblog/p/16890035.html

相关文章

  • k8s源码分析2-命令行工具cobra的使用
    本节重点介绍:kubectl的职责和kubectl的代码原理cobra库的使用简介kubectl的职责主要的工作是处理用户提交的东西(包括,命令行参数,yaml文件等)然后其会把用户提交......
  • 《STL 源码剖析》 deque 实现原理
    目录deque概述deque中控器deque迭代器和数据结构deque操作原理deque随机存储deque插入deque删除deque和stack、queue的关系deque概述deque是双向开口的连续线性空间......
  • 如何修改npm包源码后,重新npm包的时候能是修改后的版本
    肯定是clone一份到gitHub啦保存一份修改后的npm包到自己的私有库npm安装git仓库的方式npminstall<gitremoteurl>例如npminstallgithub:mygithubuser/mypro......
  • html字符串转pdf源码
        ///<summary>     ///将Html文字输出到PDF     ///</summary>     ///<paramname="htmlText......
  • Vue3源码解读之patch
    例子代码本篇将要讲解domdiff,那么咱们结合下面的例子来进行讲解,这个例子是在上一篇文章的基础上,加了一个数据变更,也就是list的值发生了改变。html中增加了一个按钮change......
  • 如何正确学习vue3.0源码
    为什么要学源码技术是第一生产力学习API的设计目的、思路、取舍学习优秀的代码风格学习组织代码的方式学习实现方法的技巧学习ES67新API、TS高级用法不给自......
  • 上帝视角看Vue源码整体架构+相关源码问答
    前言这段时间利用课余时间夹杂了很多很多事把Vue2源码学习了一遍,但很多都是跟着视频大概过了一遍,也都画了自己的思维导图。但还是对详情的感念模糊不清,故这段时间对源码......
  • React源码中的dom-diff
    这一章就来讲讲React在协调阶段的beginWork里面主要做的事情--domdiff。本文主要讲的是React17.0.2版本的diff,在此我也画了一个简单的流程图:reconcileChildrendomd......
  • 基于微信小程序的疫情核酸预约系统设计与实现-计算机毕业设计源码+LW文档
    小程序开发说明开发语言:Java框架:ssmJDK版本:JDK1.8服务器:tomcat7数据库:mysql5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:Maven3.3.9......
  • vue 项目源码映射失败问题解决
    目录vue项目源码映射失败问题解决前言解决方案效果参考vue项目源码映射失败问题解决前言不知何时起,项目控制台调试进入源代码变成编译后的文件了,调试起来十分不便,强迫......