Seata-go TCC 设计与实现

news2024/10/6 1:47:17

作者:刘月财

本文主要介绍 seata-go 中 TCC 的设计思路、异常处理以及在实战中的使用。

Seata 是一款开源的分布式事务解决方案,致力于为现代化微服务架构下的分布式事务提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 等多种事务模式,帮助用户解决不同场景下的业务问题。同时,Seata 还支持多语言编程,并且提供了简易的 API 接口、丰富的文档以及快速上手的 samples 示例项目,也能快速帮助开发者入门并上手 Seata 的使用。

Seata-go 是 Seata 多语言生态中 golang 语言的实现方案,它致力于帮助 golang 开发者也能使用 Seata 的能力来解决分布式事务场景的问题。 Seata-go 复用了 Seata TC 的能力,client 的功能和 Seata 保持一致。目前 Seata-go 已经支持了 TCC 和 AT 模式,XA 模式正在测试中,预计会在 5 月份发版。Saga 模式正在设计和规划中,后面也会和 Seata 的 Saga 功能保持一致。

本文主要从以下几个角度,介绍 Seata-go 中的 TCC 模式的设计与使用:

  • Seata-go TCC 实现原理
  • Sata-go TCC 异常处理
  • Seata-go 的展望

Seata-go TCC 实现原理

Seata-go 采用了 getty 做 TCP 网络通信,完全实现了 Seata 的通信协议。下层实现了配置中心和注册中心,也支持了很多的第三方框架的接入,比如 dubbo、grpc、gorm 等等,目前也正在积极和各个社区沟通,以支持更多框架的接入。Seata-go 简易的系统架构图如下:

在这里插入图片描述

先来简单回顾下 TCC 模式的含义。TCC 是分布式事务方案的一种实现,它采用了二阶段提交协议,TCC 的全称是 Try-Confirm-Cancel,Try 是预留资源操作,Confirm 是提交操作,Cancel 是回滚操作。在 TCC 的一阶段中,先触发所有的子事务执行 Try 操作,如果所有的子事务的一阶段都执行成功,那么会触发所有子事务二阶段执行 Confirm 操作,否则二阶段执行 Cancel 操作,以此来保证各个子事务状态的一致性。

TCC 是一种侵入式的分布式事务方案,Try、Confirm 和 Cancel 三个阶段的逻辑,都需要用户自己去实现。这样做意味着更多的代码量,以及对业务很大的入侵性;而优点是则比较灵活,能由用户随意发挥以解决更复杂的分布式事务场景的问题。

在介绍 Seata-go 的 TCC 模式之前,先来回顾下 Seata 中的三个核心角色,即 TC、TM 和 RM。TC 是事务协调者,负责维护全局事务的状态,以及触发分支事务的提交和回滚动作;TM 是事务管理器,负责子事务的编排,以及全局事务的提交和回滚动作;RM 是资源管理器,管理分支事务处理的资源,比如 MySQL 数据库的操作等。

了解了这三个核心角色,就可以大致的理解下 TCC 的事务流程,大致分为以下几个步骤:

  • TM 向 TC 发送请求,开启全局事务,TC 侧记录下全局事务的状态信息;
  • TM 分别向所有的 RM 发送请求,RM 会向 TC 注册分支事务,然后执行 Try 阶段的逻辑;
  • 如果当中某个 RM 给 TM 返回 Try 阶段执行失败,那 TM 就向 TC 发送“回滚全局事务” 的请求。TC 收到后,就会向所有已执行 Try 的 RM 发送 Rollback 指令,触发 RM 执行 Cancel 逻辑;
  • 如果所有的 RM 都给 TM 返回 Try 阶段执行成功,那 TM 就向 TC 发送“提交全局事务” 的请求。TC 收到后,就会向所有已执行 Try 的 RM 发送 Commit 指令,触发 RM 执行 Commit 逻辑。

至此,一个完整的分布式事务就执行完了,以下是这个过程的流程图:

在这里插入图片描述

在 Seata-go 中,为了方便用户使用,提供了两种定义 TCC 服务方法,一种是实现 TwoPhaseInterface 接口,具体如下:

在这里插入图片描述

另一种是通过 tag 的方式来定义 TCC 服务,这种方式会相对复杂点,但是也更加的灵活:

在这里插入图片描述

第二种 tag 的方案,主要是为了满足一些特殊的场景,比如说,dubbo-go 的 server 和 client 是使用 tag 的方式来定义的,这个时候就需要使用 tag 的方式来定义 TCC 的服务。一般情况推荐使用第一种继承接口的方式来做,比较简单。

在实际使用的时候,用户只需要做以下几件事情即可:

  • 定义好自己的 TCC 服务,可以参考上面介绍的这两种方式之一都可以;
  • 调用 TCC 的代理方法 NewTCCServiceProxy ,将 TCC 服务的封装成代理;
  • 编排好自己的子事务,传入到分布式事务的入口方法 WithGlobalTx 方法即可。

这里截图给大家看个例子,更详细的 samples 请参考 seata-go-samples 项目,地址为:https://github.com/seata/seata-go-samples

在这里插入图片描述

Seata-go TCC 异常处理

在实际使用 TCC 的时候,由于网络或是业务代码逻辑执行时间等因素,可能会出现以下的问题:

  • 幂等: 在事务的一、二阶段,由于网络延迟或是其他原因,RM 没有及时给 TC 或 TM 响应,导致 RM 被重复触发执行一、二阶段的逻辑,这个时候,需要考虑业务的幂等;
  • 空回滚: 由于网络延迟或是其他原因,RM 在未收到 Try 请求的情况下,却收到了 Rollback 请求,造成空回滚的问题;
  • 悬挂: 由于网络延迟或是其他原因,RM 在未收到 Try 请求的情况下,收到了 Rollback 请求,处理完 Rollback 请求后,又收到了 Try 请求。这时全局事务已结束,会导致事务预留的资源一直无法释放。

在 Seata-go 中,提供了两种解决方案,来帮助用户解决这个问题。

第一种方式的原理和 Seata Java 的处理逻辑是一样的,都是借助 tcc_fence_log 事务状态表来做的:

在这里插入图片描述

用户需要在自己的业务数据库中,创建这个表,RM 在提交业务 SQL 的时候,同时会在这个表里面插入一条记录,这俩 SQL 是在一个本地事务中完成的。由于这个表中,“全局事务ID+分支事务ID”是一个联合主键,导致重复执行时会失败,这样就解决了 Try 阶段的幂等问题。在 Commit 和 Cancel 阶段时,会先查询这个表中分支事务的状态,然后才进行实际的逻辑,最后再更新状态。这样也能保证 Commit 和 Cancel 阶段的幂等性。

再来看看 Seata-go 是如何解决事务悬挂和空回滚的问题。假如一个 Rollbback 请求过来,RM 去查询 tcc_fence_log 表,发现没有记录(因为 RM 尚未收到 Try 请求),此时会往 tcc_fence_log 表插入一条记录,并标记状态为 suspend,然后直接退出,而不会去执行 Rollback 的逻辑,这样就避免了空回滚的问题。如果 RM 后面再收到 Try 请求,由于 tcc_fence_log 表已经有一条记录,就会导致事务 SQL 无法提交而失败(tcc_fence_log 会出现主键冲突的问题),这样就避免了防悬挂的问题。

要实现这种方式,需要使用 Seata-go 提供的代理数据源,这些操作都会由代理数据源来完成,用户只需要开启开关,关注自己的业务 SQL 即可,这个功能已经实现,会在后续进行发版。

第二种方式,是通过用户手动的方式来实现的。原理和上面类似,但是 tcc_fence_log 的操作逻辑需要由用户自己实现,下面的截图描述了大致的使用方式,详情可以参考这个 samples 代码:

https://github.com/seata/seata-go-samples/tree/main/tcc/fence

在这里插入图片描述

Seata-go 展望

Seata-go 社区近期与不少国内 go 语言微服务框架以及 ORM 框架背后的开发社区达成合作,比如 GORM 框架,已经集成到了 Sample 中,后续会将更多的 ORM 框架集成在 Seata-go-Samples 项目中。与 MOSN 社区的合作也在推进中,可实现真正的基于 Seata 的 Transaction Mesh。

Seata-go 的 XA 模式会在5月份进行发版,届时 Seata-go 将支持 TCC、XA 和 AT 三种事务模式。Seata-go 后续的中心将会在 Saga 模式功能的开发上。

当前的 Saga 模式仅实现了服务编排的正向推进与反向 Rollback 能力,更进一步的服务编排则可以实现 DAG、定时任务、任务批量调度,覆盖工作流的所有流程,提升用户在 Seata 这个平台上的使用体验。目前 Seata-go 依赖于 Seata Java 的 TC,按照这个工作计划,可能需要在未来的 Seata-go 版本中实现一个功能更强大的 TC 调度。

Seata-go 社区目前正在快速生长中,希望有更多对开源感兴趣的小伙伴,加入到我们社区来,一起助力 Seata-go 的成长!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/554812.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IS日志文件存在哪里? Windows服务器lIS日志存放位置及查看

用户每打开一次网页,iis,都会记录用户IP、访问的网页地址、访问时间、访问状态等信息,这些信息保存在iis日志文件里,方便网站管理员掌握网页被访问情况和iis 服务器运行情况。如果网页被恶意访问(如注入数据库),日志中会有相应的记…

C++ 仿函数(二)

在上一篇里我们讲了仿函数是什么,以及一元谓词,二元谓词的概念 C 仿函数(一)_小梁今天敲代码了吗的博客-CSDN博客 这篇是讲“内建函数对象”主要包括:“算术仿函数”,“关系仿函数”,“逻辑仿函数” 目录 一.算术仿…

6年自动化测试经验,终于进字节跳动了,年薪30w其实也并非遥不可及

一些碎碎念 什么都做了,和什么都没做其实是一样的,走出“瞎忙活”的安乐窝,才是避开弯路的最佳路径。希望我的经历能帮助到有需要的朋友。 在测试行业已经混了5个年头了,以前经常听到开发对我说,天天的点点点有意思没…

LC-1373. 二叉搜索子树的最大键值和(后序遍历)

1373. 二叉搜索子树的最大键值和 难度困难173 给你一棵以 root 为根的 二叉树 ,请你返回 任意 二叉搜索子树的最大键值和。 二叉搜索树的定义如下: 任意节点的左子树中的键值都 小于 此节点的键值。任意节点的右子树中的键值都 大于 此节点的键值。任…

IP协议详解之IP地址要领

整个的因特网就是一个单一的、抽象的网络。而IP地址就是给因特网上的每一个主机(或路由器)的每一个接口分配一个在全世界范围是唯一的32位的标识符。IP地址的结构使我们可以在因特网上很方便地进行寻址。但是,根据TCP/IP协议的规定的IP地址是…

【Flutter 工程】002-代码生成:Freezed ——类似 Java 的 lombok

【Flutter 工程】002-代码生成:Freezed ——类似 Java 的 lombok 文章目录 【Flutter 工程】002-代码生成:Freezed ——类似 Java 的 lombok一、概述1、简介2、主要功能3、主页与使用前后比较主页使用前使用后 二、基本使用1、安装2、改造 main.dart3、创…

pygam第4课——颜色监测(迷宫小游戏)

前言:前三节课我们学习了,窗口的创建、图片的加载、常用鼠标事件的等。今天我们学一个颜色的监测,并自制一个迷宫小游戏。那我们一下来看看吧 前面的三节课在这里,大家记得关注收藏一下: 视频演示 1、界面搭建 背景图…

开发者关系工程师如何帮助开发者在Sui上构建

近期,我们与Sui开发者关系负责人Brian Hennessey-Hsien进行了对话,就Sui上的开源、去中心化和开发者成就等话题展开讨论。 日前,我们采访了Sui基金会的开发者关系负责人Brian Hennessey-Hsieh,共同探讨了其对于Web3中开发者发展历…

冷热温度正反向控制技术在换热器热疲劳试验中的应用

摘要:空调换热器需要进行可靠性试验以满足整机产品在不同环境下的寿命周期,温度交变试验是可靠性试验中是较为关键的一项。本文在现有PLC交变温度控制技术基础上,提出了一种模块式的改进解决方案,即增加了专用的高精度PID调节器分…

不入耳耳机的正确打开方式,韶音OpenFit诠释耳机的“舒适圈”

文 | 智能相对论 作者 | 佘凯文 总有人说,人们需要跳出舒适圈,逼着自己去不断挑战。也有人问,我满足现状,为什么要跳出舒适圈?说到底,两种说法都没有错,不过该不该走出舒适圈或许也得分“场合…

麻了,最好不要去外包,干了三年,废了一半......

先说一下自己的情况,大专生,18年通过校招进入湖南某软件公司,干了接近4年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

【coding加油站】vue单页面图书管理系统

1、引言 设计结课作业,课程设计无处下手,网页要求的总数量太多?没有合适的模板?数据库,java,python,vue,html作业复杂工程量过大?毕设毫无头绪等等一系列问题。你想要解决的问题&am…

数据结构课程设计——运动会分数统计

运动会分数统计 数据结构课程设计任务书 学生姓名:xxx 专业班级:软件工程 指导教师: 工作单位: 题 目: 运动会分数统计 基础要求: 要求具有C语言的理论基础…

ProtoBuf安装及避坑指南

文章目录 安装前注意事项(避坑)ProtoBuf在Linux下的安装protoBuf 测试demo 安装前注意事项(避坑) 1.安装前,我们需要升级g,使用较新的g编译器。 2.在安装过程中,出现问题,可以选择安装其他版本,在加压文件下执行make …

NFTScan:05.15~05.21 NFT 市场热点汇总

欢迎来到由 NFT 基础设施 NFTScan 出品的 NFT 生态热点事件每周汇总。 周期:2023.05.15 ~ 2023.05.21 NFT Hot News:NFT 热点资讯 01/ DID 解决方案提供商 Lifeform 以 3 亿美元估值完成 IDG Capital 领投的 B 轮融资 5 月 15 日,去中心化…

Rocketmq常用使用场景

RocketMQ 是阿里开源的分布式消息中间件,跟其它中间件相比,RocketMQ 的特点是纯JAVA实现 基础概念 Producer: 消息生产者,负责产生消息,一般由业务系统负责产生消息 Producer Group: 消息生产者组&#xf…

ESP32CAM---利用Vscode阅读源码

前言 (1)首先,我在此吐槽一些,arduino平台的代码阅读功能,是真滴垃圾。气死我了。配置这玩意搞了半天,还没搞好。 (2)最后我决定使用Vscode阅读arduino的代码。arduino IDE负责编译程…

智能工厂已成为制造业数字化转型的重心

我国“十四五”规划纲要提出,要深入实施智能制造和绿色制造工程,发展服务型制造新模式,推动制造业高端化智能化绿色化。随着5G等新一代信息技术与制造业不断深度融合,制造业的智能化发展成为未来我国制造业转型升级的重要方向。《…

MyBatisPlus快速入门(一)MyBatisPlus简介、历史和优势

一、什么是 MyBatisPlus?二、MyBatisPlus 相关文档2.1 官网2.2 Github源码2.3 官方文档 三、MyBatisPlus 的历史四、MyBatisPlus 的特性和优势4.1 特性4.2 优势 五、如何学习 MyBatisPlus & 专栏计划 一、什么是 MyBatisPlus? MyBatisPlus&#xff…

MyBatis中使用第三方分页插件PageHelper完成分页功能

文章目录 一、前言二、基于插件拦截方式1、自定义插件2、使用第三方插件完成分页1、分页插件的配置2、分页插件的使用 一、前言 分页是web应用程序非常重要的一个技术。数据库中的数据可能是成千上万的,不可能把这么多的数据一次显示在浏览器上面。一般根据每行数据…