当前位置:首页 > 技术分析 > 正文内容

Seata源码—1.Seata分布式事务的模式简介

ruisui884周前 (05-21)技术分析16

大纲

1.Seata分布式事务框架简介

2.Seata AT模式实现分布式事务的机制

3.Seata AT模式下的写隔离机制

4.Seata AT模式下的读隔离机制

5.官网示例说明Seata AT模式的工作机制

6.Seata TCC模式的介绍以及与AT模式区别

7.Seata Saga模式的介绍

8.单服务多个库的分布式事务支持

9.Seata的AT、TCC、Saga三种模式对比

10.基于RocketMQ的可靠消息最终一致性事务

11.Seata官方分布式事务例子


1.Seata分布式事务框架简介

(1)Seata的特色功能

(2)Seata的术语


Seata是一款分布式事务解决方案,为用户提供了ATTCCSAGAXA事务模式,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。


(1)Seata的特色功能

一.微服务框架集成支持

已支持Dubbo、Spring Cloud、Sofa-RPC、Motan和gRPC等RPC框架。


二.AT模式

提供无侵入自动补偿的事务模式,目前已支持MySQL、Oracle、PostgreSQL、TiDB和MariaDB。


三.TCC模式

支持TCC模式并可与AT混用,灵活度更高。


四.SAGA模式

为长事务提供的解决方案,提供编排式与注解式。


五.XA模式

支持已实现XA接口的数据库的XA模式,目前已支持MySQL、Oracle、TiDB和MariaDB。


六.高可用

支持计算分离集群模式,水平扩展能力强的数据库和Redis存储模式。


(2)Seata的术语

一.TC(Transaction Coordinator)—事务协调者

用来维护全局和分支事务的状态,驱动全局事务提交或回滚。


二.TM(Transaction Manager)—事务管理器

用来定义全局事务的范围:开始全局事务、提交或回滚全局事务。


三.RM(Resource Manager)—资源管理器

用来管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。


2.Seata AT模式实现分布式事务的机制

(1)前提

(2)整体机制


(1)前提

一.基于支持本地ACID事务的关系型数据库

二.Java应用 + 通过JDBC访问数据库


(2)整体机制

两阶段提交协议的演变:


一阶段:首先业务数据回滚日志记录同一个本地事务中提交,然后释放本地锁连接资源


二阶段:提交异步化,非常快速地完成,回滚通过一阶段的回滚日志进行反向补偿


3.Seata AT模式下的写隔离机制

(1)Seata在AT模式下的写隔离机制

(2)Seata在AT模式下的写隔离例子

(3)Seata AT模式写隔离下的补偿执行

(4)为什么Seata AT模式要设计写隔离机制


(1)Seata在AT模式下的写隔离机制

一阶段本地事务提交前,需要确保先拿到全局锁。如果拿不到全局锁,就不能提交本地事务。拿全局锁的尝试被限制在一定时间范围内,超出时间范围将被放弃,并回滚本地事务,释放本地锁。


(2)Seata在AT模式下的写隔离例子

以一个示例来说明:两个全局事务tx1和tx2,分别对m字段进行更新操作,m的初始值是1000。


tx1先开始,开启本地事务,拿到本地锁,更新操作m=1000-100=900。本地事务提交前先拿到该记录的全局锁本地事务提交后释放本地锁


tx2后开始,开启本地事务,拿到本地锁,更新操作m=900-100=800。本地事务提交前尝试拿该记录的全局锁


tx1全局提交前,该记录的全局锁被tx1持有,tx2需要重试等待获取全局锁。tx1二阶段全局提交,释放全局锁。tx2拿到全局锁后,提交其本地事务。


(3)Seata AT模式写隔离下的补偿执行

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


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


(4)为什么Seata AT模式要设计写隔离机制

由于整个过程全局锁在tx1结束前一直是被tx1持有的,所以写隔离机制可以保证不会发生脏写的问题。


4.Seata AT模式下的读隔离机制

(1)Seata AT模式的读隔离机制介绍

(2)Seata AT模式的读隔离机制实现


(1)Seata AT模式的读隔离机制介绍

在数据库本地事务隔离级别读已提交(Read Committed)或以上的基础上,Seata AT模式默认全局隔离级别读未提交(Read Uncommitted)


如果应用在特定场景下,必需要求全局的读已提交,目前Seata的方式是通过SELECT FOR UPDATE语句的代理来实现。


(2)Seata AT模式的读隔离机制实现

SELECT FOR UPDATE语句的执行会申请全局锁。如果全局锁被其他事务持有,则释放本地锁(回滚SELECT FOR UPDATE语句的本地执行)并重试


在这个过程中,查询是被阻塞住的。直到拿到全局锁,即读取的相关数据是已提交的,才返回。


出于总体性能上的考虑,Seata目前的方案并没有对所有SELECT语句都进行代理仅针对FOR UPDATE的SELECT语句


5.官网示例说明Seata AT模式的工作机制

(1)一阶段的工作过程

(2)二阶段——回滚的工作过程

(3)二阶段——提交的工作过程

(4)使用Seata AT模式需要创建回滚日志表


以一个示例来说明整个AT分支的工作过程:


业务表:product

+-------+--------------+-------+
| Field | Type         | Key   |
+-------+--------------+-------+
| id    | bigint(20)   | PRI   |
+-------+--------------+-------+
| name  | varchar(100) |       |
+-------+--------------+-------+
| since | varchar(100) |       |
+-------+--------------+-------+

AT分支事务的业务逻辑:

update product set name = 'GTS' where name = 'TXC';


(1)一阶段的工作过程

步骤一:解析SQL得到SQL的类型、表、条件等相关的信息。比如类型是UPDATE、表是product、条件是where name = 'TXC'。


步骤二:查询前镜像。也就是根据解析得到的条件信息,生成查询语句,定位数据。

select id, name, since from product where name = 'TXC';

//得到前镜像如下:
+-------+-------+-------+
| id    | name  | since |
+-------+-------+-------+
| 1     | TXC   |  2014 |
+-------+-------+-------+

步骤三:执行业务SQL。更新这条记录的name为'GTS'。


步骤四:查询后镜像。根据前镜像的结果,通过主键定位数据。

select id, name, since from product where id = 1;

//得到后镜像如下:
+-------+-------+-------+
| id    | name  | since |
+-------+-------+-------+
| 1     | GTS   |  2014 |
+-------+-------+-------+

步骤五:插入回滚日志。把前后镜像数据以及业务SQL相关的信息组成一条回滚日志记录,插入到UNDO_LOG表中。

{
    "branchId": 641789253,
    "undoItems": [{
        "afterImage": {
            "rows": [{
                "fields": [{
                    "name": "id",
                    "type": 4,
                    "value": 1
                }, {
                    "name": "name",
                    "type": 12,
                    "value": "GTS"
                }, {
                    "name": "since",
                    "type": 12,
                    "value": "2014"
                }]
            }],
            "tableName": "product"
        },
       "beforeImage": {
            "rows": [{
                "fields": [{
                    "name": "id",
                    "type": 4,
                    "value": 1
                }, {
                    "name": "name",
                    "type": 12,
                    "value": "TXC"
                }, {
                    "name": "since",
                    "type": 12,
                    "value": "2014"
                }]
            }],
            "tableName": "product"
        },
        "sqlType": "UPDATE"
    }],
    "xid": "xid:xxx"
}

步骤六:提交前向TC注册分支。也就是申请product表中,主键值等于1的记录的全局锁


步骤七:本地事务提交。业务数据的更新和前面步骤中生成的UNDO LOG一并提交。


步骤八:将本地事务提交的结果上报给TC


(2)二阶段——回滚的工作过程

步骤一:收到TC的分支回滚请求,开启一个本地事务执行如下操作。


步骤二:通过XID和Branch ID查找到相应的UNDO LOG记录


步骤三:拿UNDO LOG中的后镜像当前数据进行数据校验。如果有不同,说明数据被当前全局事务之外的动作做了修改。这种情况,需要根据配置策略来做处理。


步骤四:根据UNDO LOG中的前镜像和业务SQL信息生成并执行回滚语句


步骤五:提交本地事务并把执行结果(即分支事务回滚的结果)上报给TC


(3)二阶段——提交的工作过程

步骤一:收到TC的分支提交请求,把请求放入一个异步任务的队列中,然后马上返回提交成功的结果给TC。


步骤二:异步任务阶段执行分支提交请求,将异步和批量地删除相应UNDO LOG记录


(4)使用Seata AT模式需要创建回滚日志表

CREATE TABLE `undo_log` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `branch_id` bigint(20) NOT NULL,
    `xid` varchar(100) NOT NULL,
    `context` varchar(128) NOT NULL,
    `rollback_info` longblob NOT NULL,
    `log_status` int(11) NOT NULL,
    `log_created` datetime NOT NULL,
    `log_modified` datetime NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;


6.Seata TCC模式的介绍以及与AT模式区别

(1)Seata TCC模式的介绍

(2)TCC模式与AT模式的区别


(1)Seata TCC模式的介绍

TCC = Try + Commit + Cancel。一个分布式的全局事务,整体是两阶段提交的模型。全局事务是由若干分支事务组成,分支事务要满足两阶段提交的模型要求。


即需要每个分支事务都具备自己的:一阶段Prepare行为(Try行为),二阶段Commit或Rollback行为(Commit + Cancel行为)


(2)TCC模式与AT模式的区别

所谓TCC模式,是指支持把自定义的分支事务纳入到全局事务的管理中。其实一开始,Seata只有TCC模式,后来才加入AT模式。但TCC模式太麻烦了,每个功能都需要实现三套SQL逻辑,AT模式其实是对TCC模式的简化。


AT模式基于支持本地ACID事务关系型数据库

一阶段Prepare行为:在本地事务中,一起提交业务数据更新相应回滚日志记录

二阶段Commit行为:马上成功结束,自动 + 异步 + 批量清理回滚日志。

二阶段Rollback行为:通过回滚日志,自动生成补偿操作,完成数据回滚。


TCC模式不依赖于底层数据资源的事务支持:

一阶段Prepare行为:调用自定义Prepare逻辑。

二阶段Commit行为:调用自定义Commit逻辑。

二阶段Rollback行为:调用自定义Rollback逻辑。


7.Seata Saga模式的介绍

Saga模式是Seata提供的长事务解决方案。在Saga模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败补偿前面已经成功的参与者一阶段正向服务二阶段补偿服务都由业务开发实现。


Saga模式的正向服务可以理解成是TCC模式的Try阶段 + Commit阶段逆向补偿服务可以理解成是TCC模式的Cancel阶段


一.适用场景

场景一:业务流程长、业务流程多

场景二:无法提供TCC模式要求的三个接口

比如参与者包含其它公司,或者遗留的老系统服务。


二.优势

一阶段提交本地事务,无锁 + 高性能

事件驱动架构,参与者可异步执行高吞吐

补偿服务易于实现


三.缺点

不保证隔离性,写不隔离


8.单服务多个库的分布式事务支持

单个服务对接了多个库。比如该服务处理一个请求时,需要更新多个数据库。分支事务是分布在多个数据库上的,并不是分布在多个服务上的。Seata也天然支持这种情况下的分布式事务。


每个数据库上的事务也都会到Seata上注册一个分支事务。注册之后,各个分支事务也和Seata的AT模式一样申请本地锁 + 生成undo log + 申请全局锁 + 在其对应数据库上提交增删改


9.Seata的AT、TCC、Saga三种模式对比

AT模式适用于底层存储都相同的情况,比如都是MySQL等。一般选用AT模式即可,简单方便


TCC模式适用于底层存储是异构的情况,比如MySQL + Redis + ES等。TCC模式一般在try阶段写入一条数据并标记未生效状态,然后在commit阶段才正式标记为正常生效状态。


TCC模式最大的优点就是很灵活。即使事务失败了,try阶段写入的数据基本也不会影响线上业务。TCC模式特别适用于异构存储要支持事务的情况。


Saga模式适用于异构系统长流程改造成TCC特别复杂繁琐的情况。


10.基于RocketMQ的可靠消息最终一致性事务

同步事务:在Seata的ATTCCSaga中选一种

异步事务:使用RocketMQ的事务机制或者自己实现一套最终一致性事务框架


11.Seata官方分布式事务例子

https://seata.io/zh-cn/docs/user/quickstart.html

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/4181.html

标签: blob协议
分享给朋友:

“Seata源码—1.Seata分布式事务的模式简介” 的相关文章

【幼儿园收费管理系统】——中小型幼儿园收费管理的好帮手!

为了让幼儿园收费管理更加高效、便捷,我们推出了《幼儿园收费管理系统》!这款软件专为中小型幼儿园设计,集基础信息、幼儿管理、收费管理、车辆管理、生日提醒、报表统计等功能于一身,是您管理幼儿园的得力助手!一、基础设置:一款好的软件,首先要让您轻松上手。我们的系统提供了幼儿园信息、年级设置、班级设置、餐...

vue中如何在自定义组件上使用v-model和.sync

自定义事件tips推荐始终使用 kebab-case 的事件名。(v-on会将事件名自动转换为小写,避免匹配不到)changeData ×change-data √自定义组件的v-model用法:父组件定义数据源(不需要定义修改数据的方法),在子组件标签上通过v-model="data...

gitlab 分支保护设置

一、功能描述代码管理中管理,我们把稳定的分支设置为保护,可以防止其他人员误操作(例如删除,合并,推送代码等)。二、Gitlab配置步骤1 点击项目Repository标签2.点击Expand标签3.配置如下:默认master是被保护的,而且只有维护人员具有推送和合并权限。设置保护分支,这里的beta...

微信开发的五大价值应用

企业形象展示微网站是企业在移动互联网时代完美展示企业及品牌形象的最佳选择,表现内容丰富、实时更新、形式多样化,保证品牌形象的有效传播!微网站带来的轻营销模式,更适应现代网站的发展模式,所以微网站的开发也具有更好的商业营销效果,其面对的受众是7亿多的微信用户,蕴含着无限的商机。将企业微网站植入微信公众...

详解编程中的同步和异步

本文主要总结一些自己对异步的理解,话不多说 下面开始。一. 单线程 我们常说“JavaScript是单线程的”,所谓单线程,是指在JS引擎中负责解释和执行JavaScript代码的线程只有一个。不妨叫它主线程 但是实际上还存在其他的线程。例如:处理AJAX请求的线程、处理DOM事件的线程、定时器线程...

大容量SSD太贵买不起,这三种低成本方案也能让硬盘速度起飞

现在的游戏文件夹体积动不动就突破100GB,256GB、512GB容量的SSD装不了几个游戏就满了。虽说现在SSD价格一直在降,但是1TB及更大容量的SSD价格依然比较高。如果你对硬盘容量、速度有较高要求,又不想花太多预算的话,这三种低成本硬盘加速方案一定要了解一下。锐龙用户的福利——StoreMI...