Go Mysql Driver 集成 Seata-Golang 解决分布式事务问题

摘要:
简介:2020年4月,我们开始尝试实现go语言分布式事务框架Seata Golang。众所周知,SeataAT模式因其无业务代码入侵的特性而受到大多数开发人员的高度赞扬。SeataAT模式的Java版本充当DataSource数据源的代理。当执行SQL语句时,它拦截并解析SQL语句,以在执行SQL语句前后获得数据库相应数据的副本。序列化后,它将被保存,并在TC协调回滚时用于回滚相应的数据。实现go版本客户端的AT模式

简介: 2020 年 4 月,我们开始尝试实现 go 语言的分布式事务框架 Seata-Golang。众所周知,Seata AT 模式以无业务代码侵入的特点,被广大开发者推崇。Java 版 Seata AT 模式通过对 DataSource 数据源进行代理,在 sql 语句执行时,对 sql 拦截解析,获取数据库对应数据在 sql 语句执行前后的副本,序列化后保存起来,在 TC 协调回滚时用来回滚对应数据。实现 go 版本 client 的 AT 模式时,怎样对业务开发者更友好,入侵更少,成了首要考虑的目标。

头图.png

作者 | 刘晓敏  GitHub ID:dk-lockdown
来源 | 阿里巴巴云原生公众号

背景

2020 年 4 月,我们开始尝试实现 go 语言的分布式事务框架 Seata-Golang。众所周知,Seata AT 模式以无业务代码侵入的特点,被广大开发者推崇。Java 版 Seata AT 模式通过对 DataSource 数据源进行代理,在 sql 语句执行时,对 sql 拦截解析,获取数据库对应数据在 sql 语句执行前后的副本,序列化后保存起来,在 TC 协调回滚时用来回滚对应数据。实现 go 版本 client 的 AT 模式时,怎样对业务开发者更友好,入侵更少,成了首要考虑的目标。

1.png

使用 go 操作数据库时,我们会使用到 go 语言的官方库 database/sql,通过 sql.Open("mysql", ${dsn}) 获取一个数据源操作对象 db。开启事务时,使用 db.Begin() 或 db.BeginTx(ctx, &sql.TxOptions{}) 获得事务操作对象 tx,执行 sql 查询使用 tx.Query;执行 sql 新增、修改、删除,使用 tx.Exec;最后使用 tx.Commit() 提交或使用 tx.Rollback() 回滚。

go 语言官方库 database/sql 提供了一个标准抽象层,通过实现不同的 driver 一套标准的抽象 API 可以操作不同的数据库。开发 Go 版本的 AT 模式,必然要兼容 database/sql。通过研究 database/sql 的 api,创建数据源操作对象,数据库有关的配置必须通过 Data Source Name (DSN) 抽象传递进去,下面是 DSN 的定义:

[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN]

实现 AT 模式对数据源代理是需要和事务协调器 TC 进行交互的,如果将 AT 模式实现在 driver 层,那么和 TC 交互的一些参数必须要通过 DSN 传递到 driver,这样有些破坏它的设计。所以,最后采取了一种折中方案,在 database/sql 层之上实现 AT 模式,代理 database/sql 创建出来的数据源操作对象。数据源代理对象实现 database/sql 库定义的 Tx 接口,另外再提供一个开启事务的方法:Begin(),虽然没有完全兼容 database/sql 的 api,但是关键接口和它的定义成一样,勉强还能接受。到此,Seata-Golang 项目核心功能的开发已完成。

type Tx interface {
    Commit() error
    Rollback() error
}
转折

Seata-Golang  开源后,逐渐被一些开发者了解和接触,社区也对 Seata-Golang 发出了一些反馈的声音,不少开发者并不习惯写原生 sql,他们希望将 Seata-Golang 集成到 ORM 框架,因为当时的设计没有完全兼容 database/sql 导致集成上遇到一些困难。随着社区的热切呼唤,且得益于前期对 driver 的一些研究,念念不忘必有回响,今年 3 月突然灵感迸发:为什么参数一定要通过 DSN 传递?Seata-Golang Client 初始化后,在需要时通过 Client 端的 API config.GetATConfig() 直接获取使用不就可以了。

2.png

于是工作之余,历时 2 周开发,第一个集成 Seata-Golang 的完全兼容 database/sql 的 mysql driver 被开发出来,项目开源在 https://github.com/opentrx/mysql,现处于 beta 状态,希望社区开发者使用后能有一些反馈,可通过例子:https://github.com/opentrx/seata-go-samples,查看使用方式并进行测试。

driver 的一些细节
  • 使用该 driver 进行分布式事务操作时,不能在 dsn 中设置 interpolateParams 参数为 true。

这涉及到 mysql 的两个协议:Text 协议和 Binary 协议。有关两个协议的区别,可以在文末参考文档找到资料。实现该 driver 只对 binary 协议进行了处理,开启 interpolateParams 会使用 text 协议执行 sql。

  • 使用该 driver 在需要加入全局事务组和 tc 进行交互时,需要使用 db.BeginTx(ctx context.Context, opts driver.TxOptions) 方法,并在 ctx 中加入 XID 全局事务 id 的值。
ctx := context.WithValue(context.Background(), mysql.XID, c.Request.Header.Get("XID"))
tx, err := dao.BeginTx(ctx, &sql.TxOptions{
        Isolation: sql.LevelDefault,
        ReadOnly:  false,
    })

XID 传递到 driver 层,会保存在 &mysqlConn 连接对象中,在和 TC 交互时用到。

  • 使用该 driver 的分布式事务功能前需要先初始化 seata-golang client 和 mysql driver:
  config.InitConf(configPath)
  client.NewRpcClient()
  mysql.InitDataResourceManager()
  mysql.RegisterResource(config.GetATConfig().DSN)

具体可参考 seata-go-samples

寄语

此项目开源到今年 4 月即满一年,通过本文中的 mysql driver,希望能降低使用门槛,让大家真正用起来,大家在选择微服务开发技术栈时也不用担心 go 语言没有分布式事务处理方案。

本文为阿里云原创内容,未经允许不得转载。

免责声明:文章转载自《Go Mysql Driver 集成 Seata-Golang 解决分布式事务问题》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇system 系统调用、gcc编译过程【转】Pixel-Fillrate下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

数据库(二)—— MySQL索引优化

MySQL的索引优化 目录 MySQL的索引优化 一、MySQL 5.7的初始化配置 二、MySQL配置文件 1、配置 2、配置文件作用 三、多实例 1、创建相关的目录 2、创建实例的配置文件 3、初始化 4、授权 5、启动实例 6、查看启动状况 7、测试 8、配置启动脚本 9、开机自启 10、设定mysql密码 11、忘记密码 四、数...

Doris开发手记1:解决蛋疼的MySQL 8.0连接问题

笔者作为Apache Doris的开发者,平时感觉相关Doris的文章写的很少。主要是很多时候不知道应该去记录一些怎么样的问题,感觉写的不好就会很慌张。新的一年,希望记录自己在Doris开发过程之中所遇到一些有意思的事情。(只希望能坚持下来,别打脸~~)言归正传,回到本篇想聊的问一个问题,笔者在开发ODBC of Doris的工作之中,发现通过MySQL...

聊聊 Python 数据处理全家桶(Sqlite篇)

1. 前言 上篇文章 聊到 Python 处理 Mysql 数据库最常见的两种方式,本篇文章继续说另外一种比较常用的数据库:Sqlite Sqlite 是一种 嵌入式数据库,数据库就是一个文件,体积很小,底层由 C 语言编写,经常被集成到移动应用程序中 事实上,Python 内置了 sqlite3 模块,不需要安装任何依赖,就可以直接操作 Sqlite...

MySQL高可用方案--MHA部署及故障转移

架构设计及必要配置 主机环境 IP                 主机名             担任角色 192.168.192.128  node_master    MySQL-Master| MHA-Node 192.168.192.129  node_slave     MySQL-Slave | MHA-Node(备选Master) 19...

mis系统的技术需求

  所谓MIS(管理信息系统--Management Information System)系统,主要指的是进行日常事务操作的系统。这种系统主要用于管理需要的记录,并对记录数据进行相关处理,将处理的信息及时反映给管理者的一套网络管理系统。   开发一个mis系统需要用到eclipse,还需要tomcat和mySQL。   tomcat安装、配置过程:首先下...

mysql(4)—— 表连接查询与where后使用子查询的性能分析。

子查询就是在一条查询语句中还有其它的查询语句,主查询得到的结果依赖于子查询的结果。 子查询的子语句可以在一条sql语句的FROM,JOIN,和WHERE后面,本文主要针对在WHERE后面使用子查询与表连接查询的性能做出一点分析。 对于表连接查询和子查询性能的讨论众说纷纭,普遍认为的是表连接查询的性能要高于子查询。本文将从实验的角度,对这两种查询的性能做出验...