那些用Go实现的分布式事务框架之二

那些用Go实现的分布式事务框架之二

作者:吴亲库里 2021-12-15 10:00:21

开发

后端

分布式 seata中的TM对标dtm事务SDK。作用都是一样:第一阶段开启一个全局事务,执行各RM分支事务,第二阶段根据RM第一阶段执行结果,决定调用TC(seata)|TM(dtm) commit或者rollback。

[[440473]]

本文转载自微信公众号「RememberGo」,作者吴亲库里。转载本文请联系RememberGo公众号。

开篇

上一篇那些用Go实现的分布式事务框架我们主要介绍的是seata-golang。一个对标seata的go语言实现,当然版本还是落后Java版很多的。

这次我们来介绍一下另一个go实现的分布式事务:dtm。

首先来看下dtm整体架构图(来源官网)。

再来看之前的seata架构图。

从架构上来看,大差不差。

seata中的TC对标dam的TM。

RM两边意思一致。

seata中的TM对标dtm事务SDK。作用都是一样:第一阶段开启一个全局事务,执行各RM分支事务,第二阶段根据RM第一阶段执行结果,决定调用TC(seata)|TM(dtm) commit或者rollback。

架构上,个人感觉只是因为模块名称以及图画不一样的差别,当然在实现细节上还是有很大差别的。

我们先简单介绍下DTM各个模块。

TM

TM 层在代码中是没有具体的主体结构的,开始都是函数之前的调用。

启动TM实际上开启了两个服务,http以及grpc这两个服务。

http路由,

gRPC接口,

即然提供了两个服务入口,那理所当然有公共处理核心业务的部分。

TM对数据的存储管理并不是依赖于接口,而是依赖于common.DB 结构。根据配置文件中DB.driver 的值决定底层数据库是mysql还是postgres两种。

再看这个DB结构,所以本质上无论底层是哪种数据库,都是直接依赖gorm来对数据进行操作的。

接着,看下TM是如何通知各个RM进行commit或者rollback的?

举一个TCC模式的例子。

TCC的两个阶段。

  • 阶段一: try。尝试执行,调用各RM自定义的try行为,预留必要的业务资源。
  • 阶段二:Confirm(阶段一所有参与本次事务的try行为都成功)。调用各分支事务的Confirm方法,真正执行业务,并且只使用try阶段预留的资源。
  • 阶段二:Cancel(阶段一任一参与本次事务的try行为失败)。调用各分支事务的Cancel方法,释放一阶段try所预留的资源。

从上面我们可以得知,TCC模式下,TM在第二阶段要么通知各分支事务Confirm要么Cancel。

在注册各RM事务分支到TM的时候,最终TM会为每一个分布式事务的参与者(RM)生成两条分支信息。

就像这样,

对,就是把对应的RM资源操作地址直接存入。

当TM接收到commit或者rollback命令,在处理完自身逻辑(一般就是修改Gloable状态),就需要开始处理每一个注册进来的分支事务了,说白了就是需要调用各个分支事务对应操作的接口。

这里的t.getProcessor() 是需要根据当前事务的类型(TCC、SAGA、XA)获取到对应的处理器来进行逻辑的处理。

当然,每个事务处理器只需要实现接口,

真正调用RM资源服务地址的时候,分为http和grpc,这是由开发者决定的。

在v1.6之前的版本,grpc的请求是很简单粗暴解析地址方法然后连接的。

现在为了支持那些采用gRPC Resolver 机制之上的一些微服务框架接入,做了一块抽象。感兴趣[1]可以看下,这里就不介绍了。

SDK

至于SDK,每一个事务模式都是独立的,本质上是没有关联的。比如下面我们启动一个TCC分布式事务。这个分布式事务是由两个服务组成,简称+30和-30的服务。

  • 从上面的调用中我们还是能还原出整体流程。
  • 调用TM,得到一个分布式id
  • 调用TccGlobalTransaction函数开启分布式事务。
  • 调用TM prepare(这步只是为了查看第一步产生的那个分布式事务状态是否处于prepare。这里没看明白,此时还未注册执行分支,全局状态不是应该只会存在初始化状态吗)
  • 上一步没问题,执行传入的闭包函数,即CallBranch 函数里向TM注册参与事务的TM分支。注册完成后,开始第一阶段调用各分支的try服务。
  • 各分支try服务调用结束,根据第一阶段结果决定通知TM是submit还是abort。

另外提一点,分布式事务常见的一些问题:比如空补偿、重挂等问题。

一般情况下,业务需要自行去处理这种场景,以免造成不可描述的错误。

dtm里面提供了对应子事务屏障方案。核心就在,

其实就是利用数据库的唯一索引机制,当然每个RM资源你都得新增一张表。

上面提到,dtm的TM角色本质上就是对应 seata 中的 TC,但是他们的处理模式是不同的。

dtm中的TM会根据注册时的各分支保存的地址,决定通过http还是rpc调用各RM操作,是由TM直接发起对RM的请求。

seata-go的实现中,TC是不参与直接调用RM的。

还记得上篇提到一个双向流RPC接口(BranchCommunicate)。TC通过这个接口把对应分支处理信息传递给RM管理器。

然后由RM管理器根据事务类型选择对应的事务管理器进行处理,最终调用的是对应事务类型管理器的BranchCommit方法。

下面是一个TCC事务类型管理器的处理。

对应的事务RM管理器是如何通知、处理各个RM资源的。

原理就是我上篇提到的作者实现的一个全局事务代理模式,本质上是利用go的反射实现的,感兴趣的可以自己去扒下源码,也可以看看作者对实现全局事务代理的介绍[2]。

总结

这篇文章主要介绍了dtm实现的一些细节,从这两篇文章大体能看出实现上的部分区别,更多的细节还得靠自己去挖掘。

最后再问几个问题,

  • 日常开发中你们哪些场景是用到了分布式事务?用的是哪个框架还是自研的?
  • 或者说在分布式环境下,一致性的问题你们是如何解决的?

相关

https://zhuanlan.zhihu.com/p/351391359

https://dtm.pub/protocol/support.html

 

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/268336.html<

(0)
运维的头像运维
上一篇2025-05-06 20:22
下一篇 2025-05-06 20:23

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注