属于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 。

4dc4243f552f5c28842ed3fb5286c780.png

事务提交、回滚

通过 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

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

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

相关文章

iOS 直接使用16进制颜色

在做iOS开发时,一般我们会吸色,就是产品给的图我们一般会吸色,但是最近吸色时候,老大说有较大的颜色偏差,所以要求我们直接使用UI给出的额16进制颜色,你也可以搜索《RGB颜色值转换成十六进制颜色码&#xf…

如何在mfc主对话框中再显示子对话框_win10扩展显示器设置方法

使用win10系统的过程中,常常需要对win10系统扩展显示器进行设置。良多对电脑不太认识的用户不知道win10系统扩展显示器到底该如何设置?实在win10系统扩展显示器的设置方法非常简朴,下面小编教你win10扩展显示器设置方法。一些用户使用电脑时需要运行多个…

每天CookBook之JavaScript-059

向页面添加元素<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>059</title><style type"text/css">.overlay{background-color: #000;opacity: .7;filter: alpha(opacity70);po…

蓝牙驱动卸载后自动安装_Intel 蓝牙驱动安装教程

前言可能有些人之前没有搞定Intel蓝牙的驱动&#xff0c;今天就把蓝牙的驱动也发一下&#xff0c;实现Intel全家桶的驱动&#xff0c;到处倒腾换网卡也是挺折腾的。所支持的蓝牙IDIntelBluetoothFirmware 是一个用于在 macOS 中启用原生蓝牙的固件上传驱动&#xff0c;固件的二…

Java设计模式笔记(1)单例模式

单例模式&#xff1a;确保某一个类只有一个实例&#xff0c;而且自行实例化并向整个系统提供这个实例。 package com.juno.SinglePattern; // 饿汉式单例&#xff0c;通用代码&#xff0c;建议 public class SingletonOne {private static final SingletonOne instance new Si…

PHP中的常用关键字

PHP中常用的关键字&#xff1a;final 、static、const。。。。 final &#xff1a; 1、final不能修饰成员属性 2、final只能修饰类和方法 final作用&#xff1a; 1、使用final修饰的类不能被子类继续 2、使用final修饰的方法不能被子类去覆盖 3、用来限制类不被继承&#xff0c…

cad在线转低版本_为什么别人制图那么快?41个CAD实用技巧,3天轻松玩转CAD

获取更多业界资讯和深度好文● 点击蓝字关注我们 ●点击上方蓝色字体 关注我们我们在使用CAD制图时&#xff0c;总感觉自己的速度非常慢&#xff0c;为什么别人可以那么快的制图呢&#xff1f;今天就给大家分享一些CAD实用技巧&#xff0c;让你3天轻松玩转CAD。一、提高绘图效率…

Java设计模式笔记(2)工厂方法模式

工厂方法模式&#xff1a;定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。 在工厂方法模式中&#xff0c;抽象产品类Product负责定义产品的共性&#xff0c;实现对事物最抽象的定义&#xff1b; Creator为抽象创建…

资料收藏夹

一、学习&#xff1a; 视达网 (ps教程,ps视频教程,电商运营,海报,平面设计,字体设计,c4d教程,ai教程,每天免费学习一个视频教程) Cinema 4D 视频教程 虎课网 (ps教程,ps视频教程,电商运营,海报,平面设计,字体设计,c4d教程,ai教程,每天免费学习一个视频教程) Cinema 4D 视频教…

不同协议的数据包如何处理_【项目申报专员】如何处理各种不同的项目申报工作呢...

前文我们说到了在企业做项目申报专员需要掌握的政策查询&#xff0c;以及申报流程解读工作&#xff0c;今天我给大家来分享在企业如何做好对不同项目的申报工作。说这个问题之前&#xff0c;我们先得了解一些背景知识。在企业做项目申报专员工作意味着什么&#xff1f;意味着事…

Java设计模式笔记(3)抽象工厂模式

抽象工厂模式&#xff1a;为创建一组相关的或者相互依赖的对象提供一个接口&#xff0c;而且无需指定他们的具体类。 抽象工厂模式是工厂方法模式的升级版本&#xff0c;在有多个业务品种、业务分类时&#xff0c;通过抽象工厂模式产生需要的对象是一种非常好的解决方式。 pac…

jsoup简单的爬取网页数据

/*** Project Name:JavaTest* File Name:BankOfChinaExchangeRate.java* Package Name:com.lee.javatest* Date:2016年7月22日下午1:34:09* Copyright (c) 2016年7月22日, Pwenlee All Rights Reserved.* */package com.lee.javatest;import java.io.Serializable; import java…

sql每个月每个人的花销占比_11月:每个认真生活的人,都值得被认真对待

恍然已11月&#xff0c;风吹枯叶落&#xff0c;落叶生肥土&#xff0c;肥土滋养着果实&#xff0c;果实缓慢而坚定着成长。图片&#xff5c;东海青 摄图片&#xff5c;子夜鸟 摄11月&#xff0c;不要怂这是属木芙蓉的晚秋。花朵娇嫩&#xff0c;它却无所忌惮地美丽着&#xff0…

Java设计模式笔记(4)模版方法模式

模版方法模式&#xff1a;定义一个操作中的算法的框架&#xff0c;而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些步骤。 抽象模版的方法分为两类&#xff1a; 1. 基本方法也叫基本操作&#xff0c;是由子类实现的方法&#xff0c;并且在…

比较TFS与SVN,你必须知道的10点区别

相比SVN&#xff0c;对于TFS的优点我有以下几点看法&#xff0c;供大家参考&#xff1a; 1. 总体比较&#xff1a; TFS是一个应用软件生命周期管理&#xff08;ALM&#xff09;软件&#xff0c;是一个软件研发平台产品&#xff0c;其功能覆盖了软件研发过程中的所有环节&#…

react textarea 空格为什么不换行_你需要的 React + TypeScript 50 条规范和经验

这篇文章没有对错之分&#xff0c;肯定也有不完善的地方&#xff0c;结合了自己日常开发和经验。可以让你书写代码更具严谨性,希望看完之后有所帮助。本文字数4000 &#xff0c;看完本文大概需半小时。1. 注释(1) 文件顶部的注释&#xff0c;包括描述、作者、日期/** * descrip…

Java设计模式笔记(5)建造者模式

建造者模式&#xff1a;将一个复杂对象的构建与它的表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 建造者模式的4个角色&#xff1a; Product产品类&#xff1a;通常是实现了模版方法模式&#xff0c;有模版方法和基本方法。 Builder抽象建造者&#xff1a;规…

Three.js基础探寻二——正交投影照相机

本篇主要介绍照相机中的正交投影照相机。   第一篇传送门&#xff1a;Three.js基础探寻一 1.照相机 图形学中的照相机定义了三维空间到二维屏幕的投影方式。 针对投影方式照相机分为正交投影照相机和透视投影照相机。 2.两种相机的区别与适用范围 正交投影&#xff1a; 透视投…

centos删除文件夹_等保测评主机安全之centos密码长度

密码长度&#xff0c;作为等级保护主机测评项里中密码复杂度要求之一&#xff0c;是必须要查的。在《等级测评师初级教程》里&#xff0c;对于密码长度的设置指向了/etc/login.defs里的PASS_MIN_LEN字段。# PASS_MIN_LEN Minimum acceptable password length.PASS_MIN_LEN …

【原创】Android之修改AlertDialog对话框及使用系统Holo风格

前一阵子在做伪装密码的功能&#xff0c;需要使用系统的对话框&#xff0c;对话框需要加长按事件等等。哈&#xff0c;直接上代码&#xff0c;我是比较喜欢直接看代码的。 1. 获取AlertDialog的Title final int alertTitleId getResources().getIdentifier( "alertTitle…