属于db模式缺点的是什么_详解 Seata Golang 客户端 AT 模式及其使用
源码:point_down: seata-golang
概述
我们知道 Seata Java Client 的 AT 模式,通过代理数据源,实现了对业务代码无侵入的分布式事务协调机制,将与 Transaction Coordinator (TC) 交互的逻辑、Commit 的逻辑、Rollback 的逻辑,隐藏在切面和代理数据源相应的代码中,使开发者无感知。那如果这个方法,要用 Golang 来实现一遍,应该如何操作呢?关于这个问题,我想了很久,最初的设想是,对 database/sql 的 mysql driver 进行增强,在对包 github.com/go-sql-driver/mysql 研究了一段时间后,还是没有头绪,不知如何下手,最后转而增强 database/sql 包。由于 AT 模式必须保证本地事务的正确处理,在具体业务开发时,首先要通过 db.Begin() 获得一个 Tx 对象,然后再 tx.Exec() 执行数据库操作,最后 tx.Commit() 提交或 tx.Rollback() 回滚。这种处理方式算是一个 Golang 数据库事务处理的基本操作。 所以对 database/sql 的增强,我们重点关注这几个方法 db.Begin() 、 tx.Exec() 、 tx.Commit() 、 tx.Rollback 。
事务提交、回滚
通过 Seata Java Client 的相关代码,我们知道,在本地事务提交的时候,主要是将分支事务注册到 TC 上,并将数据库操作产生的 undoLog 一起写入到 undoLog 表;本地事务回滚的时候,需要将分支事务(即本地事务)的执行状态报告给 TC,使 TC 好知道是否通知参与全局事务的其他分支回滚。
func (tx *Tx) Commit() error { //注册分支事务branchId,err := tx.register()if err != nil {return errors.WithStack(err)}tx.tx.Context.BranchId = branchIdif tx.tx.Context.HasUndoLog() { //将 undoLog 写入 undoLog 表err = manager.GetUndoLogManager().FlushUndoLogs(tx.tx)if err != nil {err1 := tx.report(false)if err1 != nil {return errors.WithStack(err1)}return errors.WithStack(err)}err = tx.tx.Commit()if err != nil {err1 := tx.report(false)if err1 != nil {return errors.WithStack(err1)}return errors.WithStack(err)}} else {return tx.tx.Commit()}if tx.reportSuccessEnable {tx.report(true)}tx.tx.Context.Reset()return nil}
db.Begin() 会产生一个 Tx 对象, tx.Exec() 会产生 undoLog, tx.Commit() 将 undoLog 刷到数据库中。那么 undoLog 保存到哪里呢?答案是 Tx_Context 中。
type TxContext struct {*context.RootContextXid stringBranchId int64IsGlobalLockRequire boolLockKeysBuffer *model.SetSqlUndoItemsBuffer []*undo.SqlUndoLog}
Commit() 方法中的 tx.tx.Context ,第一个 tx 是封装的 Tx 对象,第二个 tx 是 database/sql 的 Tx, tx.tx.Context 则是 Tx_Contex。UndoLogManager 则是操作 undoLog 的核心对象,处理 undoLog 的插入、删除,并查询出 undoLog 用于回滚。
func (tx *Tx) Rollback() error {err := tx.tx.Rollback()if tx.tx.Context.InGlobalTransaction() && tx.tx.Context.IsBranchRegistered() { // 报告 TC 分支事务执行失败tx.report(false)}tx.tx.Context.Reset()return err}
通过上面的代码呢,我们知道增强型 Tx 对象需要向 TC 注册分支事务,并报告分支事务的执行状态,相应代码如下:
func (tx *Tx) register() (int64,error) {return dataSourceManager.BranchRegister(meta.BranchTypeAT,tx.tx.ResourceId,"",tx.tx.Context.Xid,nil,tx.tx.Context.BuildLockKeys())}func (tx *Tx) report(commitDone bool) error {retry := tx.reportRetryCountfor retry > 0 {var err errorif commitDone {err = dataSourceManager.BranchReport(meta.BranchTypeAT, tx.tx.Context.Xid, tx.tx.Context.BranchId,meta.BranchStatusPhaseoneDone,nil)} else {err = dataSourceManager.BranchReport(meta.BranchTypeAT, tx.tx.Context.Xid, tx.tx.Context.BranchId,meta.BranchStatusPhaseoneFailed,nil)}if err != nil {logging.Logger.Errorf("Failed to report [%d/%s] commit done [%t] Retry Countdown: %d",tx.tx.Context.BranchId,tx.tx.Context.Xid,commitDone,retry)retry = retry -1if retry == 0 {return errors.WithMessagef(err,"Failed to report branch status %t",commitDone)}}}return nil}
和 TC 进行通信的主要逻辑还是在 DataSourceManager 里面。AT 模式涉及的两个关键对象 DataSourceManager、UndoLogManager 就浮出水面。一个用于远程 TC 交互,一个用于本地数据库处理。
事务执行
func (tx *Tx) Exec(query string, args ...interface{}) (sql.Result, error) {var parser = p.New() // 解析业务 sqlact,_ := parser.ParseOneStmt(query,"","")deleteStmt,isDelete := act.(*ast.DeleteStmt)if isDelete {executor := &DeleteExecutor{tx: tx.tx,sqlRecognizer: mysql.NewMysqlDeleteRecognizer(query,deleteStmt),values: args,}return executor.Execute()}insertStmt,isInsert := act.(*ast.InsertStmt)if isInsert {executor := &InsertExecutor{tx: tx.tx,sqlRecognizer: mysql.NewMysqlInsertRecognizer(query,insertStmt),values: args,}return executor.Execute()}updateStmt,isUpdate := act.(*ast.UpdateStmt)if isUpdate {executor := &UpdateExecutor{tx: tx.tx,sqlRecognizer: mysql.NewMysqlUpdateRecognizer(query,updateStmt),values: args,}return executor.Execute()}return tx.tx.Tx.Exec(query,args)}
执行业务 sql,并生成 undoLog 的关键,在于识别业务 sql 执行了什么操作:插入?删除?修改?这里使用 tidb 的 sql parser 去解析业务 sql,再使用相应的执行器去执行业务 sql,生成 undoLog 保存在 Tx_Context 中。
事务开启
db.Begin() 返回增强型的 Tx 对象。
func (db *DB) Begin(ctx *context.RootContext) (*Tx,error) {tx,err := db.DB.Begin()if err != nil {return nil,err}proxyTx := &tx2.ProxyTx{Tx: tx,DSN: db.conf.DSN,ResourceId: db.GetResourceId(),Context: tx2.NewTxContext(ctx),}return &Tx{tx: proxyTx,reportRetryCount: db.conf.ReportRetryCount,reportSuccessEnable: db.conf.ReportSuccessEnable,},nil}
seata-golang at 模式的使用
sample 代码
- 首先执行 scripts 脚本,初始化数据库
如果之前没有初始化过 seata 数据库,先执行 seata-golang/scripts/server/db/mysql.sql 脚本 - 修改 dsn 数据库配置,修改下列文件:
seata-golang/tc/app/profiles/dev/config.ymlseata-golang/samples/at/product_svc/conf/client.ymlseata-golang/samples/at/product_svc/conf/client.yml
- 将下列文件中的 configPath 修改为 client.yml 配置文件的路径
seata-golang/samples/at/product_svc/main.goseata-golang/samples/at/order_svc/main.goseata-golang/samples/at/aggregation_svc/main.go
- 依次运行 tc、order_svc、product_svc、aggragation_svc,访问下列地址开始测试:
http://localhost:8003/createSoCommithttp://localhost:8003/createSoRollback
属于db模式缺点的是什么_详解 Seata Golang 客户端 AT 模式及其使用相关推荐
- python策略模式包含角色_详解Python设计模式之策略模式
虽然设计模式与语言无关,但这并不意味着每一个模式都能在每一门语言中使用.<设计模式:可复用面向对象软件的基础>一书中有 23 个模式,其中有 16 个在动态语言中"不见了,或者简 ...
- java性能最好的mvc框架_详解Spring MVC的异步模式(高性能的关键)
什么是异步模式 要知道什么是异步模式,就先要知道什么是同步模式,先看最典型的同步模式: 浏览器发起请求,Web服务器开一个线程处理,处理完把处理结果返回浏览器.好像没什么好说的了,绝大多数Web服务器 ...
- x86 - CPU架构/寄存器详解 (三) 保护模式
系列文章 x86 - CPU架构/寄存器详解 (一)x86.8086.i386.IA-32 是什么? x86 - CPU架构/寄存器详解 (二) 实模式(8086模式) x86 - CPU架构/寄存器 ...
- LVS原理详解(3种工作模式及8种调度算法)
2017年1月12日, 星期四 LVS原理详解(3种工作模式及8种调度算法) LVS原理详解及部署之二:LVS原理详解(3种工作方式8种调度算法) 作者:woshiliwentong 发布日期:20 ...
- 模糊匹配 读音_onenote搜索机制详解②:两种搜索模式,模糊与精确匹配
先从纯文本搜索讲起,这是最基本也是最重要的. 从这篇开始,以及接下来连续几篇文章,都会介绍搜索的基础功能.注意,这几篇文章中谈论的都是基本的.正常的搜索功能,暂时不考虑Bug等因素. 在很多软件(例如 ...
- 工程之星android版使用,安卓版工程之星软件网络1+1模式及网络cors连接操作详解...
原标题:安卓版工程之星软件网络1+1模式及网络cors连接操作详解 现在,越来越多用户开始使用安卓版工程之星进行作业,科力达技术工程师总结了安卓版工程之星网络1+1模式及网络CORS连接方式操作步骤, ...
- java 配置jmstemplate_SpringBoot集成JmsTemplate(队列模式和主题模式)及xml和JavaConfig配置详解...
1.导入jar包: org.springframework.boot spring-boot-starter-activemq org.apache.activemq activemq-pool 2. ...
- 命令行模式下几个网络命令详解
命令行模式下几个网络命令详解 上一篇 / 下一篇 2007-05-16 16:20:55 查看( 166 ) / 评论( 0 ) / 评分( 0 / 0 ) 命令行模式下几个网络命令详解 一.pin ...
- 大脑构造图与功能解析_大脑的结构和功能分区_详解人脑构造与功能
大脑的结构和功能分区 _ 详解人脑构造与功能 学习,可以开阔人的大脑 ; 学习,可以使人的大脑拥有更多的知识,人的大脑和肢 体一样,多用则灵,不用则废.那么下面学习啦小编给大家分享一些大脑的结构和功 ...
最新文章
- mysql减少锁等待_降低锁竞争 减少MySQL用户等待时间
- CADisplayLink 及定时器的使用
- 在mysql查询数据库密码_如何查询mysql数据库密码
- 2015.4.25-2015.5.1 字符串去重,比例圆设计,中奖机和canvas橡皮擦效果等
- linux如何把nfs数据导出来,linux – NFS导出已经挂载NFS的目录(在服务器上)
- PowerDesigner生成数据库时的列中文注释乱码问题[mysql]
- OData debug - Java client - why my batch request fails
- Oracle Java Mission Control:终极指南
- 不受支持的SQL类型1111
- gcc for linux安装失败,安装错误的gcc导致一些错误
- windows 7旗舰版升级windows 10专业版,全过程
- PC网站实现微信扫码登录功能(二)
- kali攻击139端口_入侵445端口-永恒之蓝漏洞利用-Metasploit
- C盘清理的五大技巧,瞬间多出30G
- linux什么时候挂载根文件系统,什么时候要重新制作Linux的根文件系统?谢谢
- cadence软件选择网络功能
- 百家号自媒体如何写文章标题,百家号怎么写标题
- 如何快速通过阿里云ACP 认证?
- 匿名突破网络限制 (Tor工作原理分析)
- 2021年北京值得去的100家规模互联网大厂公司全名简称
热门文章
- Android 生成随机数,获取一条随机字符串
- yarn 安装 sass
- Mac下Apache使用
- java -jar maven项目打包提示.jar中没有主清单属性
- centos中nodejs npm环境完全删除
- Java中BigDecimal的8种舍入模式
- Linux给Java程序设置端口_扫描服务端口的Java程序
- java提高篇四_(转)java提高篇(四)-----理解java的三大特性之多态
- mysql 去除warning_zabbix监控mysql之去掉烦人的warning告警语句
- 【Makefile由浅入深完全学习记录2】初识 makefile 的结构