SDK

支持的语言

go

这里的client都是dtm/client里面内容的同步复制。采用这里的包,而不是dtm,会让你的应用程序依赖更少,包体更小

client: https://github.com/dtm-labs/client

最简示例: https://github.com/dtm-labs/quick-start-sample

关于SDK使用的最全的示例,包括了grpc/http/xa/msg/saga/tcc/barrier 等等,都合并在下面这个项目

https://github.com/dtm-labs/dtm-examples

相关博客

php

客户端sdk 协程版(支持Hyperf、SAGA、TCC、MSG、XA、子事务屏障)https://github.com/dtm-php/dtm-client

示例:https://github.com/dtm-php/dtm-sample

上述SDK由PHP界大佬黄朝晖发起,并亲自操刀设计,主要代码由PandaLIU-1111贡献,并获得Swool创始人推荐,代码质量高,社区活跃

普通版客户端sdk(当前只支持TCC): https://github.com/dtm-labs/dtmcli-php

示例: https://github.com/dtm-labs/dtmcli-php-sample

感谢 onlyshow 的帮助,php的sdk和示例,主要由他完成

相关博客

dotnet

客户端sdk http版本(支持TCC、SAGA、MSG、子事务屏障): https://github.com/dtm-labs/dtmcli-csharp

示例: https://github.com/dtm-labs/dtmcli-csharp-sample

感谢 catcherwonggeffzhang的帮助,C#的sdk和示例,主要由他们贡献

客户端sdk grpc版本:https://github.com/catcherwong/dtmgrpc-csharp

相关博客

python

客户端sdk(当前支持TCC、SAGA、子事务屏障): https://github.com/dtm-labs/dtmcli-py

示例: https://github.com/dtm-labs/dtmcli-py-sample

相关博客

Java

客户端sdk(SAGA、TCC、子事务屏障): https://github.com/dtm-labs/dtmcli-java

示例: https://github.com/dtm-labs/dtmcli-java-sample

感谢 li-xiao-shuangviticis Kui Liao的帮助,Java的sdk和示例,主要由他们贡献

相关博客

node

客户端sdk(当前只支持TCC): https://github.com/dtm-labs/dtmcli-node

示例: https://github.com/dtm-labs/dtmcli-node-sample

相关博客

其他

如果这里没有找到您熟悉的语言,同时您又想运行dtm,看看一个分布式事务什么样,您可以参考这里:

DTM安装运行

如果你是通过brew 安装,那么您可以直接运行

  1. dtm-qs

上述dtm-qs命令,会运行一个简单的quick start例子,这是一个saga事务,您可以对照saga的时序图与日志,更深入的了解dtm

支持的数据库

dtm的SDK中,提供了子事务屏障功能,也提供了XA相关的支持,这部分的支持是与具体的数据库相关的。目前已支持了常见的几种数据库事务,包括Mysql系列、Postgres,Redis、Mongo。未来将考虑接入更多的数据库事务

Mysql 系列

包括Mysql,MariaDB,TiDB,TDSQL

Postgres

已完整支持Postgres,如果您使用Postgres,需要在使用SDK前,进行如下调用

  1. dtmcli.SetCurrentDBType("postgres")

详细例子,可以参考dtm/app/main.go中的代码

Redis

DTM 已支持 Redis 事务,这样用户可以在一个分布式事务里,组合使用 Redis 及 Mysql ,可以将扣库存放在 Redis 中,提供准确扣库存的架构,让订单系统可以轻松应对秒杀场景

Mongo

DTM已支持Mongo

ORM 对接

概述

dtm中的子事务屏障,需要与数据库交互,xa事务模式,也需要与数据库交互。目前dtm定义的交互接口,采用了与标准库sql兼容的方式,使用中,直接传递sql.DB/sql.Tx即可。

因为barrier需要在事务内部操作barrier相关的表,所以它的接口需要传入一个 *sql.Tx或 *sql.DB

  1. func (bb *BranchBarrier) Call(tx *sql.Tx, busiCall BusiFunc) error
  2. func (bb *BranchBarrier) CallWithDB(db *sql.DB, busiCall BusiFunc) error

Xa事务模式中,本地数据库连接是由dtmcli创建和管理的,因此调用回调函数的参数类型是 *sql.DB 。如果您使用其他的库,例如gorm等,那么您根据 *sql.DB 构建相关的orm对象即可。

  1. type XaLocalFunc func(db *sql.DB, xa *Xa) (interface{}, error)

目前 dtm 的示例,只给出了gorm的,其他orm,暂时在此说明文档中说明用法

GORM

示例在 dtm-examples

barrier示例:

  1. barrier := MustBarrierFromGin(c)
  2. // gdb is a *gorm.DB
  3. tx := gdb.Begin()
  4. return dtmcli.ResultSuccess, barrier.Call(tx.Statement.ConnPool.(*sql.Tx), func(tx1 *sql.Tx) error {
  5. return tx.Exec("update dtm_busi.user_account set balance = balance + ? where user_id = ?", -req.Amount, 2).Error
  6. })

xa示例:

  1. return dtmcli.XaLocalTransaction(c.Request.URL.Query(), BusiConf, func(db *sql.DB, xa *dtmcli.Xa) error {
  2. // gorm提供接口,可以从标准的sql.DB对象,构造gorm.DB
  3. gdb, err := gorm.Open(mysql.New(mysql.Config{
  4. Conn: db,
  5. }), &gorm.Config{})
  6. if err != nil {
  7. return nil, err
  8. }
  9. dbr := gdb.Exec("update dtm_busi.user_account set balance=balance-? where user_id=?", reqFrom(c).Amount, 1)
  10. return dbr.Error
  11. })

GOQU

barrier示例:

  1. dialect := goqu.Dialect("mysql")
  2. sdb, err := dbGet().DB.DB()
  3. if err != nil {
  4. return nil, err
  5. }
  6. gdb := dialect.DB(sdb)
  7. // gdb is a goqu dialect.DB, the following code shows how to obtain tx
  8. tx, err := gdb.Begin()
  9. return dtmcli.ResultSuccess, barrier.Call(tx, func(tx1 *sql.Tx) error {
  10. _, err := tx.Exec("update dtm_busi.user_account set balance = balance + ? where user_id = ?", -req.Amount, 2)
  11. return err
  12. })

xa示例

  1. return dtmcli.XaLocalTransaction(c.Request.URL.Query(), BusiConf, func(db *sql.DB, xa *dtmcli.Xa) error {
  2. dialect := goqu.Dialect("mysql")
  3. godb := dialect.DB(db)
  4. _, err := godb.Exec("update dtm_busi.user_account set balance=balance-? where user_id=?", reqFrom(c).Amount, 1)
  5. return err
  6. })

XORM

请注意,2021-08-21刚给xorm提了pr,暴露了sql.Tx,虽然已合并,但是还未发布版本,因此需要安装最新版本

  1. go get -u xorm.io/xorm@7cd6a74c9f

barrier示例:

  1. x, _ := xorm.NewEngineWithDB("mysql", "dtm", core.FromDB(sdbGet()))
  2. se := x.NewSession()
  3. defer se.Close()
  4. err := se.Begin()
  5. if err != nil {
  6. return nil, err
  7. }
  8. // se is a xorm session, the following code shows how to obtain tx
  9. return dtmcli.ResultSuccess, barrier.Call(se.Tx().Tx, func(tx1 *sql.Tx) error {
  10. _, err := se.Exec("update dtm_busi.user_account set balance = balance + ? where user_id = ?", -req.Amount, 2)
  11. return err
  12. })

xa示例

  1. return dtmcli.XaLocalTransaction(c.Request.URL.Query(), BusiConf, func(db *sql.DB, xa *dtmcli.Xa) error {
  2. xdb, _ := xorm.NewEngineWithDB("mysql", "dtm", core.FromDB(db))
  3. _, err := xdb.Exec("update dtm_busi.user_account set balance=balance-? where user_id=?", reqFrom(c).Amount, 1)
  4. return err
  5. })

Go-zero

需要go-zero >= v1.2.0

barrier示例:

  1. // 假设conn为go-zero里面的 sqlx.SqlConn
  2. db, err := conn.RawDB()
  3. if err != nil {
  4. return err
  5. }
  6. return dtmcli.ResultSuccess, barrier.CallWithDB(db, func(tx *sql.Tx) error {
  7. _, err := tx.Exec("update dtm_busi.user_account set balance = balance + ? where user_id = ?", -req.Amount, 2)
  8. return err
  9. })

xa示例

  1. return dtmcli.XaLocalTransaction(c.Request.URL.Query(), BusiConf, func(db *sql.DB, xa *dtmcli.Xa) error {
  2. conn := NewSqlConnFromDB(db)
  3. _, err := conn.Exec("update dtm_busi.user_account set balance=balance-? where user_id=?", reqFrom(c).Amount, 1)
  4. return err
  5. })

ent

可以支持,代码示例待补充