首页 > 其他分享 >聊聊Seata分布式解决方案AT模式的实现原理

聊聊Seata分布式解决方案AT模式的实现原理

时间:2023-05-20 11:22:20浏览次数:57  
标签:聊聊 事务 Seata 本地 回滚 提交 全局 TC 分布式

什么是Seata分布式事务解决方案

Seata是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。为用户提供了AT、TCC、SAGA和XA事务模式,为用户打造一站式的分布式解决方案。

AT模式

AT模式目前来看是Seata框架独有的一种模式,其它的分布式框架上并没有此种模式的实现。其是由二阶段提交演变来的,解决了二阶段提交的同步阻塞等问题。
演变后的两阶段提交协议:

  • 一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
  • 二阶段:
    • 提交异步化,非常快速地完成。
    • 回滚通过一阶段的回滚日志进行反向补偿。

Seata框架中有三个概念要阐述下。

  • TC:事务协调器,它是独立的组件,需要独立部署运行,Seata提供了这个独立运行的程序,它负责维护全局事务的运行状态,接收TM指令发起全局事务的提交与回滚,负责与RM通信,协调各个分支事务的提交或回滚。
  • TM:事务管理器,TM需要嵌入应用程序,它负责开启一个全局事务,并定义全局事务的范围,它的目的是最终向TC发起全局提交或回滚指令。
  • RM:与TC通信,控制分支事务,负责分支注册、报告分支事务状态,并接收事务协调器TC的指令,命令分支事务完成本地事务的提交或回滚。

流程示意图如下:

image

这个图还是比较清晰地,建议是先好好的理解下全流程。

Seata AT模式的具体流程如下。
(1)订单服务收到请求,订单服务中的TM向TC申请开启一个全局事务。(2)TC收到请求,创建一个全局事务,并将全局事务ID(称为XID)返回给订单服务的TM。
(3)订单服务的RM向TC注册分支事务。
(4)订单服务执行本地分支事务的业务逻辑并提交,释放锁定的数据库资源。
(5)订单服务向TC上报本地分支事务的提交结果。
(6)订单服务调用远程的积分服务,此时将XID通过参数传给积分服务。(7)积分服务向TC注册分支事务。
(8)积分服务执行本地分支事务的业务逻辑并提交,释放锁定的数据库资源,并返回订单服务。
(9)积分服务向TC上报本地分支事务的提交结果。
(10)订单服务的TM向TC发起全局事务的提交或回滚。
(11)TC向XID管辖下的全部分支事务发出提交或回滚的指令。

实现原理

我个人觉得框架其实也是一种需求的兑现,只是不像平常开发时那样有产品经理给你输出需求文档(应该也会有,但是少),业务流程不是传统的那种XXX业务,框架的需求一般是偏向技术一些,我把它认为是技术需求;而日常我们做的开发一般是业务需求的兑现。

上面的流程可以看作是需求,那么现在需求出来了,程序猿要怎么实现?

设计思路

TM的设计

流程的开始与结束是由TM决定的,这个TM就是订单服务Controller入口进去后的某个Service方法(当然也可能不是,看你的代码架构,我这里只按照我自己的平常的开发模式来。)在这个Service方法中,处理了订单服务以及积分服务的业务。当Service方法完成后,那么就是整个业务做完了,事务即完成。因此,要我来实现,这个TM对应的Service方法,我会选择用一个注解包裹,通过动态代理的方式,在这个方法的前后分别负责全局事务的开始与结束流程。

RM的设计

RM负责执行具体的业务,将数据入库同时上报给TC。由于二阶段回滚时需要根据回滚日志replay,那么就一定需要记录业务数据执行的日志。那怎么记录?回想了下Mybatis中的数据源代理,这里也是一样的思路。必须拦截或是代理原先的数据源,解析原执行的sql,注入Seata的逻辑,增强其执行逻辑。我们看下RM要做的事情,第一阶段:

image

第二阶段提交:

image

第二阶段回滚:

image

在执行sql的过程中,各个代理对象起到的作用如下

image

所以在RM端最关键的就是数据源代理以及远程通信。这两块尤其是前者,就是AT模式的技术实现。

TC的设计

TC端需要管理Seata全局事务会话信息,一般是由全局事务、分支事务、全局锁构成,对应表globaltable、branchtable、lock_table。因此在安装部署的时候(file模式除外)都会创建这三个表。从上面来看,目前我们还没有实现隔离性,所谓的隔离性是指多个用户并发访问数据库时,数据库为每个用户开启的事务不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。这也是这里有一个全局锁表的原因。每次本地事务提交前,都会向TC端申请注册分支,同时还会申请全局锁,RM端通过拿到的全局锁保证了读写的隔离性,因此一旦当前事务持有全局锁,那么其他的事务不能提交。

写隔离

两个全局事务 tx1 和 tx2,分别对 a 表的 m 字段进行更新操作,m 的初始值 1000。

  1. tx1 先开始,开启本地事务,拿到本地锁,更新操作 m = 1000 - 100 = 900。本地事务提交前,先拿到该记录的全局锁 ,本地提交释放本地锁。
  2. tx2 后开始,开启本地事务,拿到本地锁,更新操作 m = 900 - 100 = 800。本地事务提交前,尝试拿该记录的全局锁,tx1 全局提交前,该记录的全局锁被 tx1 持有,tx2 需要重试等待全局锁。
  3. tx1 二阶段全局提交,释放全局锁。tx2 拿到全局锁提交本地事务。

image

如果 tx1 的二阶段全局回滚,则 tx1 需要重新获取该数据的本地锁,进行反向补偿的更新操作,实现分支的回滚。

此时,如果 tx2 仍在等待该数据的全局锁,同时持有本地锁,则 tx1 的分支回滚会失败。分支的回滚会一直重试,直到 tx2 的全局锁等锁超时,放弃全局锁并回滚本地事务释放本地锁,tx1 的分支回滚最终成功。

因为整个过程全局锁在 tx1 结束前一直是被 tx1 持有的,所以不会发生脏写的问题。

image

读隔离

image

seata at 模式默认的隔离级别为读未提交(因为已经提交的sql有可能会回滚)。如果要实现读已提交,select语句需要更改为 SELECT FOR UPDATE 语句。

SELECT FOR UPDATE 语句的执行会申请全局锁,如果全局锁被其他事务持有,则释放本地锁(回滚 SELECT FOR UPDATE 语句的本地执行)并重试。这个过程中,查询是被 block 住的,直到 全局锁 拿到,即读取的相关数据是已提交的,才返回。

总结

Seata AT可以给你带来一种“无侵入”式的编程体验,你不需要改动任何业务代码,只需要一个注解和少量的配置信息,就可以实现分布式事务。

总结来看,AT模式主要是是基于 DataSource 代理实现的,通过代理 DataSource、Connection、PreparedStatement,拦截 SQL 执行,增强其执行逻辑,由代理侧加入额外的能力以提供分布式事务服务类似自动挡驾驶模式,分布式事务这个强大且复杂的服务能力由Seata框架托管,对业务实现无侵入式,用户仍然只专注于业务 SQL。

标签:聊聊,事务,Seata,本地,回滚,提交,全局,TC,分布式
From: https://www.cnblogs.com/zhiyong-ITNote/p/17416945.html

相关文章

  • 通过docker启动seata-server
    1、获取镜像(需要获取和自己依赖匹配的版本),这里我获取的是1.4.2dockerpullseataio/seata-server:1.4.22、启动镜像,将seata-server的配置文件复制到当前系统中随便启动以下dockerrun--nameseata-server-p8091:8091-dseataio/seata-server:1.4.2将配置文件所在的文件......
  • 性能测试-JMeter分布式测试及其详细步骤
    性能测试概要性能测试是软件测试中的一种,它可以衡量系统的稳定性、扩展性、可靠性、速度和资源使用。它可以发现性能瓶颈,确保能满足业务需求。很多系统都需要做性能测试,如Web应用、数据库和操作系统等。性能测试种类非常多,有些概念也很相近:LoadTestingBaselineTestingSmok......
  • 聊聊原生拖拽API
    拖拽api是我们前端非常常见的api了,比如拖拽排序,拖拽上传文件,树形结构的生成等等都会用到拖拽api,拖拽api本身不复杂难得是在应用上,下面用一个例子来简单使用下这些api先实现布局如下第一步:我们需要把左侧的元素变成可拖拽的,我们可以使用html属性给元素加一个draggable属性把它......
  • 分布式和集群部署架构设计
    一、微服务部署架构设计方案1、先采用微服务架构设计,将工程拆分成多个模块(通过接口彼此调用,降低代码的耦合度)2、后采用分布式工作方式将拆分开的各个模块分别部署到多台服务器上(通过缩短单个任务的执行时间来提升效率)3、再采用集群物理方式将各个模块部署到多台服务器上(通过提......
  • 分布式系统关键技术:流量与数据调度
    1、流量调度与服务治理的关系服务治理时内部系统的事,流量调度可以是内部的,更是外部接入层的事。服务治理时数据中心的事,而流量调度要做的好,应该是数据中心之外的事,也就是我们常说的边缘计算或者CDN。 2、流量调度的主要功能和关键技术流量调度系统应该主要具备的功能:依据系......
  • 分布式事务一致性与本地消息表
    我个人比较推崇本地消息表模式来实现最终一致性。首先本地消息表的设计不仅可以解决事务一致性的问题,对于消息队列常见问题中的消息丢失与消息幂等其实都是可以通过本地消息表来解决;其带来的好处是多重的。什么是分布式事务一致性大白话就是对数据源进行拆分后,多库多机器的多数......
  • 分布式系统关键技术:服务调度
    1、服务关键程度服务关键程度,主要是梳理和定义服务的重要程度。这不是使用技术可以完成的,而是需要细致地管理对业务的理解,才能定义出架构中各个服务的重要程度。 2、服务依赖关系梳理出服务间的依赖关系,这点也非常重要。我们常说,“没有依赖,就没有伤害”。这句话的意思就是说......
  • java-raft框架之atomix进行分布式管理
    共识算法在一个分布式的系统中,管理各个节点的一致性(共识)一直是个很有难度的问题。在近几十年的发展中,于1990年诞生的Paxos算法是其中最为经典的代表,并一统江湖数几十载。如著名的zookeeper、chubby都是基于Paxos算法的经典应用。不过Paxos算法的复杂度和难以理解性,也吸引了一些大佬......
  • 分布式事务理解
    分布式系统:是一个硬件或软件组件分布在不同的网络计算机上,彼此之间仅仅通过消息传递进行通信和协调的系统。分布式事务:是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。根据分布式系统CAP定理和base理论可知,分布式系统只......
  • 聊聊Mybatis集成Spring的原理
    一般都是研究框架源码,我为什么要反过来研究集成原理呢?在我自己看来,集成虽然比较简单,但要求的细节比较多,需要掌握根本性的东西才能做到集成。Mybatis集成Spring用到了FactoryBean以及BeanDefinition注册的原理,从这两个维度来实现集成,而我们单独学习Spring时,一般会忽略这两点。My......