Fescar(Seata)-Springcloud流程分析-1阶段
Fescar是阿里18年开源的分布式事务的框架。Fescar的开源对分布式事务框架领域影响很大。作为开源大户,Fescar来自阿里的GTS,经历了好几次双十一的考验,一经开源便颇受关注。今天就来看了Fescar的代码,看看到底是怎么一回事。
Fescar与XA两阶段提交
在XA协议中分为两阶段:
第一阶段:事务管理器要求每个涉及到事务的数据库预提交(precommit)此操作,并反映是否可以提交.
第二阶段:事务协调器要求每个数据库提交数据,或者回滚数据。
优点: 尽量保证了数据的强一致,实现成本较低,在各大主流数据库都有自己实现,对于MySQL是从5.5开始支持。
缺点
1、同步阻塞问题。执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。
2、单点故障。由于协调者的重要性,一旦协调者发生故障。参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。(如果是协调者挂掉,可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题)
3、数据不一致。在二阶段提交的阶段二中,当协调者向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这回导致只有一部分参与者接受到了commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器则无法执行事务提交。于是整个分布式系统便出现了数据部一致性的现象。
4、二阶段无法解决的问题:协调者再发出commit消息之后宕机,而唯一接收到这条消息的参与者同时也宕机了。那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道事务是否被已经提交。
Fescar虽然是二阶段提交协议的分布式事务,但是其解决了上面XA的一些缺点:
- 单点问题:虽然目前Fescar(0.4.1)还是单server的,但是Fescar官方预计将会在0.5.x中推出HA-Cluster,到时候就可以解决单点问题。
- 同步阻塞:Fescar的二阶段,其再第一阶段的时候本地事务就已经提交释放资源了,不会像XA会再两个prepare和commit阶段资源都锁住,并且Fescar,commit是异步操作,也是提升性能的一大关键。
- 数据不一致:如果出现部分commit失败,那么fescar-server会根据当前的事务模式和分支事务的返回状态的结果来进行不同的重试策略。并且fescar的本地事务会在一阶段的时候进行提交,其实单看数据库来说在commit的时候数据库已经是一致的了。
- 只能用于单一数据库: Fescar提供了两种模式,AT和MT。在AT模式下事务资源可以是任何支持ACID的数据库,在MT模式下事务资源没有限制,可以是缓存,可以是文件,可以是其他的等等。当然这两个模式也可以混用。
同时Fescar也保留了接近0业务入侵的优点,只需要简单的配置Fescar的数据代理和加个注解,加一个Undolog表,就可以达到我们想要的目的。
Fescar整合springcloud
这里直接下载 fescar-samples
项目的readme写的很详细
准备工作 执行sql/all_in_one.sql 下载0.4.1版本server 客户端与服务端版本号保持一致 启动fescar server sh fescar-server.sh 8091 ../data/ 启动business、storage、account、order 数据库默认连接127.0.0.1:3306,不同的注意修改 事务成功 GET http://127.0.0.1:8084/purchase/commit 事务回滚 GET http://127.0.0.1:8084/purchase/rollback
看了下项目的依赖和配置文件,和常规的项目相比,多了下面几个依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-fescar</artifactId>
<version>2.1.0.BUILD-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.fescar</groupId>
<artifactId>fescar-spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.fescar</groupId>
<artifactId>fescar-spring</artifactId>
<version>0.4.1</version>
</dependency>
启动相应的项目,观察相应的数据变化,这个demo算是跑起来
Fescar的实现
Fescar将一个本地事务做为一个分布式事务分支,所以若干个分布在不同微服务中的本地事务共同组成了一个全局事务,结构如下。

事务发起
观察整个demo项目,唯一不同的就是多了个注解 @GlobalTransactional 所以我先从这个注解入手
在 fescar-spring 包中发现了 com.alibaba.fescar.spring.annotation.GlobalTransactionalInterceptor这个类,这个类实现了org.aopalliance.intercept.MethodInterceptor
已动态代理的方式提供了对GlobalTransactional 注解方法的支持

最终我们的逻辑会到 com.alibaba.fescar.tm.api.TransactionalTemplate#execute方法中

execute方法是事务一阶段的核心,主要做了以下几件事情
1.构造一个全局事务
2.开始事务
通过 TmRpcClient 请求TC server端,注册一个全局的事物。得到一个全局事务id:XID,将这个XID设置到上下文中
3.执行原始的业务代码
在springcloud中我们用feign去请求其他服务,fescar对feign进行了重写,在org.springframework.cloud.alibaba.fescar.feign.FescarFeignClient中fescar对每个feign的请求都会做一次判断,如果在全局上下文中含有事务id,feign的请求头会带上XID

4.事务的回滚或者提交
提交和回滚本质上都是构造一个请求,请求远程的TC server端

5.清除ThreadLocal中的钩子函数,我们暂时还没用到。
事务参与
参与者在收到feign请求时,首先会被org.springframework.cloud.alibaba.fescar.web.FescarHandlerInterceptor拦截,拦截器会把请求中的XID设置到本地的全局上下文中

然后参与者就开始执行本地的业务。fesca在这里做了大量的背后工作。为了能在jdbc连接中添加了自己的逻辑,fesca重写了Statment之前的逻辑

JdbcTemplate数据源被配置成了Fescar实现DataSourceProxy,进而控制了后续的数据库连接使用的是Fescar提供的ConnectionProxy,Statment使用的是Fescar实现的StatmentProxy,最终Fescar就顺理成章地实现了在本地事务执行前后增加所需要的逻辑
获取代理数据源

获取代理连接

获取代理statement

在PreparedStatementProxy中,真正的执行sql的逻辑被放在了ExecuteTemplate中

根据sqltype,这里有多个executor,感觉和mybatis的代码风格有点相似

这里我们已UpdateExecutor为例

executor.execute(args);这行代码入口在com.alibaba.fescar.rm.datasource.exec.BaseTransactionalExecutor#execute
将ConnectionProxy与Xid(事务ID)进行绑定,这样后续判断当前本地事务是否处理全局事务中只需要看ConnectionProxy中Xid是否为空

再执行com.alibaba.fescar.rm.datasource.exec.AbstractDMLBaseExecutor#doExecute
这里会判断是否是自动提交

如果是自动提交,就会先设置为为非自动提交再执行executeAutoCommitFalse

这里 executeAutoCommitFalse方法是整个逻辑的核心

先查询Update前对应行记录的快照beforeImage,再执行Update语句,完成后再查询Update后对应行记录的快照afterImage,最后将beforeImage、afterImage生成UndoLog追加到Connection上下文ConnectionContext中
如果一切顺利,最终我们会执行本地事务的提交,即执行com.alibaba.fescar.rm.datasource.ConnectionProxy#commit方法,最终逻辑会到com.alibaba.fescar.rm.datasource.ConnectionProxy#processGlobalTransactionCommit

逻辑如下
1.注册分支事务到TC server端
2再将ConnectionContext中的UndoLog写入到undo_log表中
3然后调用targetConnection对本地事务进行commit,将UndoLog与业务SQL一起提交
4最后上报分支事务的状态(成功 or 失败),并将ConnectionContext上下文重置
事务的参与者便完成了自己的逻辑。二阶段中的一阶段的逻辑便是上述代码,这里再引用一张官方的流程图

Fescar(Seata)-Springcloud流程分析-1阶段的更多相关文章
- Fescar(Seata)-Springcloud流程分析-2阶段
上文我们分析了fescar的一阶段执行过程.在一阶段中,服务起始方发起全局事务并注册到TC.在调用协同服务时,协同服务的事务分支事务会先完成阶段一的事务提交或回滚,并生成事务回滚的undo_log日志 ...
- python 带参与不带参装饰器的使用与流程分析/什么是装饰器/装饰器使用注意事项
一.什么是装饰器 装饰器是用来给函数动态的添加功能的一种技术,属于一种语法糖.通俗一点讲就是:在不会影响原有函数的功能基础上,在原有函数的执行过程中额外的添加上另外一段处理逻辑 二.装饰器功能实现的技 ...
- MSM8909中LK阶段LCM屏适配与显示流程分析(二)
1.前言 在前面的文章MSM8909中LK阶段LCM屏适配与显示流程分析(一),链接如下: https://www.cnblogs.com/Cqlismy/p/12019317.html 介绍了如何使 ...
- 阶段5 3.微服务项目【学成在线】_day17 用户认证 Zuul_01-用户认证-用户认证流程分析
1 用户认证 1.1 用户认证流程分析 用户认证流程如下: 访问下面的资源需要携带身份令牌和jwt令牌,客户端可以通过身份认证的令牌从服务端拿到长令牌, 一会要实现认证服务请求用户中心从数据库内来查询 ...
- u-boot 流程分析
u-boot 介绍: 对于计算机来说 , 从一开始上机通电是无法直接启动操作系统的 , 这中间需要一个引导过程 , 嵌入式Linux系统同样离不开引导程序 , 这个启动程序就叫启动加载程序(Boot ...
- thttpd和cgilua安装与运行流程分析
安装 参考如下博文安装thttpd软件 http://blog.csdn.net/21aspnet/article/details/7045845 http://blog.csdn.net/drago ...
- u-boot启动流程分析(2)_板级(board)部分
转自:http://www.wowotech.net/u-boot/boot_flow_2.html 目录: 1. 前言 2. Generic Board 3. _main 4. global dat ...
- SQL Server中CURD语句的锁流程分析
我只在数据库选项已开启“行版本控制的已提交读”(READ_COMMITTED_SNAPSHOT为ON)中进行了观察. 因此只适用于这种环境的数据库. 该类数据库支持四种不同事务隔离级别,下面分别观察数 ...
- MapReduce运行流程分析
研究MapReduce已经有一段时间了.起初是从分析WordCount程序开始,后来开始阅读Hadoop源码,自认为已经看清MapReduce的运行流程.现在把自己的理解贴出来,与大家分享,欢迎纠错. ...
随机推荐
- 「SDOI 2018」反回文串
题目大意: 求字符集大小为$k$长度为$n$的经循环移位后为回文串的数量. 题解: 这题是D1里最神的吧 考虑一个长度为$n$回文串,将其循环移位后所有的串都是满足要求的串. 但是显然这样计算会算重. ...
- BZOJ_4870_[Shoi2017]组合数问题_矩阵乘法
BZOJ_4870_[Shoi2017]组合数问题_矩阵乘法 Description Input 第一行有四个整数 n, p, k, r,所有整数含义见问题描述. 1 ≤ n ≤ 10^9, 0 ≤ ...
- Java开源生鲜电商平台-安全设计与架构(源码可下载)
Java开源生鲜电商平台-安全设计与架构(源码可下载) 说明:Java开源生鲜电商平台是一个B2B的生鲜电商平台,由于是APP的一种模式,所以安全方面一般会思考以下几个维度: 1.数据安全. 2.传输 ...
- Treap与fhq_Treap学习笔记
1.普通Treap 通过左右旋来维护堆的性质 左右旋是不改变中序遍历的 #include<algorithm> #include<iostream> #include<c ...
- JAVA线程及简单同步实现的原理解析
线程 一.内容简介: 本文主要讲述计算机中有关线程的相关内容,以及JAVA中关于线程的基础知识点,为以后的深入学习做铺垫.如果你已经是高手了,那么这篇文章并不适合你. 二.随笔正文: 1.计算机系统组 ...
- 安卓开发笔记(三十):自定义Button
在笔者本人看了很多博客和书之后,发现很少博主对于自定义控件能够进行一个比较全面的思路讲解,大多数都是只讲了一些细节,但并没有讲如何把代码进行整体的实现.因此这里讲讲整体的自定义button实现的详细过 ...
- [Objective-C语言教程]简介(1)
中文名:扩充C的面向对象编程语言 外文名:Objective-C 简 写:ObjC&OC 创始人:布莱德·考克斯 创始时间:1980年代 Objective-C,通常写作ObjC或OC和较少用 ...
- Bagging之随机森林
随机森林(Random Forest)是一种Bagging(Bootstrap Aggregating)集成算法,在样本随机(样本扰动)的基础上,进一步运用特征随机(属性扰动)的机制,得到比一般的Ba ...
- HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
题图:by @Olga Hi,大家好,我是承香墨影! HTTP 协议在网络知识中占据了重要的地位,HTTP 协议最基础的就是请求和响应的报文,而报文又是由报文头(Header)和实体组成.大多数 HT ...
- redis测试实践
最近测试服务端的时候,接触到了redis,之前也看过,但不系统,借着这次实践,记录一下. 一.写在前面 Redis是一个开源的使用ANSI C语言编写.遵守BSD协议.支持网络.可基于内存亦可持久化的 ...