SDK
Supported languages
go
Repository client
here are a copy of the contents inside the dtm project. Using the packages here, instead of dtm, will give your application fewer dependencies and smaller packages
client: https://github.com/dtm-labs/client
Minimalist example: https://github.com/dtm-labs/quick-start-sample
The most complete examples of SDK usage, including grpc/http/xa/msg/saga/tcc/barrier, etc., are combined in the following project
https://github.com/dtm-labs/dtm-examples
php
Client sdk concurrent version (supports Hyperf, SAGA, TCC, MSG, XA, subtransaction barriers) https://github.com/dtm-php/dtm-client
Example: https://github.com/dtm-php/dtm-sample
The above SDK is designed and reviewed by Huang Chaohui, a famous coder in PHP, and is mainly contributed by (PandaLIU-1111)[https://github.com/PandaLIU-1111]. It is with high code quality and has a active community, and also recommended by the founder of Swool.
Common client sdk (currently only support TCC): https://github.com/dtm-labs/dtmcli-php
Example: https://github.com/dtm-labs/dtmcli-php-sample
Thanks to onlyshow for help with the php sdk and examples, mainly done by him
dotnet
Client sdk http version (supports TCC, SAGA, MSG, subtransaction barriers): https://github.com/dtm-labs/dtmcli-csharp
Example: https://github.com/dtm-labs/dtmcli-csharp-sample
Thanks to catcherwong, geffzhang for their help with the C sdk and examples, mainly contributed by them
Client-side sdk grpc version: https://github.com/catcherwong/dtmgrpc-csharp
python
Client sdk (currently supports TCC, SAGA, subtransaction barriers): https://github.com/dtm-labs/dtmcli-py
Example: https://github.com/dtm-labs/dtmcli-py-sample
Java
Client sdk (TCC, subtransaction barrier): https://github.com/dtm-labs/dtmcli-java
Example: https://github.com/dtm-labs/dtmcli-java-sample
Thanks to li-xiao-shuang, viticis for their help with the Java sdk and examples, mainly contributed by them
node
Client sdk (currently only supports TCC): https://github.com/dtm-labs/dtmcli-node
Example: https://github.com/dtm-labs/dtmcli-node-sample
Other
If you don't find a language you are familiar with here, and you want to run dtm to see what a distributed transaction looks like, you can refer here.
DTM installation and operation
If you are installing via brew, then you can just run
dtm-qs
The above dtm-qs command will run a simple quick start example, which is a saga transaction, you can compare the saga timing diagram and logs to get a deeper understanding of dtm
Supported databases
The SDK of dtm provides subtransaction barrier function and also provides XA related support, this part of the support is related to the specific database. Currently several common database transactions are supported, including Mysql series, Postgres, Redis, Mongo and more database transactions will be considered for access in the future
Mysql series
including Mysql, MariaDB, TiDB, TDSQL
Postgres
Postgres is fully supported, if you use Postgres, you need to make the following calls before using the SDK
dtmcli.SetCurrentDBType("postgres")
For a detailed example, you can refer to the code in dtm/app/main.go
Redis
DTM has supported Redis transactions, so that users can use a combination of Redis and Mysql in a distributed transaction, you can put the deducted inventory in Redis, to provide accurate deducted inventory architecture, so that the order system can easily cope with the spike scenario
Mongo
DTM has supported Mongo
ORM access
Overview
The subtransaction barrier in dtm, which requires interaction with the database, and the xa transaction model, which also requires interaction with the database. The current interaction interface defined by dtm adopts a standard library sql compatible way, users can pass sql.DB/sql.Tx directly.
Because the barrier needs to manipulate the barrier-related tables inside the transaction, its interface needs to be passed a *sql.Tx or *sql.
func (bb *BranchBarrier) Call(tx *sql.Tx, busiCall BusiFunc) error
func (bb *BranchBarrier) CallWithDB(db *sql.DB, busiCall BusiFunc) error
In Xa transaction mode, the local database connection is created and managed by dtmcli, so the argument type for calling the callback function is *sql.DB . If you are using another library, such as gorm, then you can just build the relevant orm object based on *sql.DB.
type XaLocalFunc func(db *sql.DB, xa *Xa) (interface{}, error)
The current dtm example, only shows how to use gorm. Other orm's access is only described here.
GORM
Example in dtm-examples
barrier example.
barrier := MustBarrierFromGin(c)
// gdb is a *gorm.DB
tx := gdb.Begin()
return dtmcli.ResultSuccess, barrier.Call(tx.Statement.ConnPool.(*sql.Tx), func(tx1 *sql.Tx) error {
return tx.Exec("update dtm_busi.user_account set balance = balance + ? where user_id = ?" , -req.Amount, 2).Error
})
xa Example.
dtmcli.XaLocalTransaction(c.Request.URL.Query(), BusiConf, func(db *sql.DB, xa *dtmcli.Xa) error {
// gorm provides an interface to construct gorm.DB from the standard sql.
gdb, err := gorm.Open(mysql.New(mysql.Config{
Conn: db,
}), &gorm.Config{})
if err ! = nil {
return nil, err
}
dbr := gdb.Exec("update dtm_busi.user_account set balance=balance-? where user_id=?" , reqFrom(c).Amount, 1)
return dbr.Error
})
GOQU
Example of a barrier.
dialect := goqu.Dialect("mysql")
sdb, err := dbGet().DB.DB()
if err ! = nil {
return nil, err
}
gdb := dialect.DB(sdb)
// gdb is goqu dialect.DB, the following code shows how to get tx
tx, err := gdb.Begin()
return dtmcli.ResultSuccess, barrier.Call(tx, func(tx1 *sql.Tx) error {
_, err := tx.Exec("update dtm_busi.user_account set balance = balance + ? where user_id = ? ", -req.Amount, 2)
Return err
})
xa example
dtmcli.XaLocalTransaction(c.Request.URL.Query(), BusiConf, func(db *sql.DB, xa *dtmcli.Xa) error {
dialect := goqu.Dialect("mysql")
godb := dialect.DB(db)
_, err := godb.Exec("update dtm_busi.user_account set balance=balance-? where user_id=?" , reqFrom(c).Amount, 1)
return err
})
XORM
Example of an barrier.
x, _ := xorm.NewEngineWithDB("mysql", "dtm", core.FromDB(sdbGet()) )
se := x.NewSession()
defer se.Close()
err := se.Begin()
if err ! = nil {
return nil, err
}
// se is an xorm session, the following code shows how to get tx
return dtmcli.ResultSuccess, barrier.Call(se.Tx().Tx, func(tx1 *sql.Tx) error {
_, err := se.Exec("update dtm_busi.user_account set balance = balance + ? where user_id = ? ", -req.Amount, 2)
Return err
})
xa example
return dtmcli.XaLocalTransaction(c.Request.URL.Query(), BusiConf, func(db *sql.DB, xa *dtmcli.Xa) error {
xdb, _ := xorm.NewEngineWithDB("mysql", "dtm", core.FromDB(db))
_, err := xdb.Exec("update dtm_busi.user_account set balance=balance-? where user_id=?" , reqFrom(c).Amount, 1)
return err
})
go-zero
Example of a barrier.
// Assuming conn is sqlx.SqlConn inside go-zero
db, err := conn.RawDB()
if err ! = nil {
return err
}
return dtmcli.ResultSuccess, barrier.CallWithDB(db, func(tx *sql.Tx) error {
_, err := tx.Exec("update dtm_busi.user_account set balance = balance + ? where user_id = ? ", -req.Amount, 2)
Return err
})
xa example
return dtmcli.XaLocalTransaction(c.Request.URL.Query(), BusiConf, func(db *sql.DB, xa *dtmcli.Xa) error {
conn := NewSqlConnFromDB(db)
_, err := conn.Exec("update dtm_busi.user_account set balance=balance-? where user_id=?" , reqFrom(c).Amount, 1)
return err
})
ent
Can be supported, code example to be added