更多功能特性
大部分的功能特性,已经在相关的文档里详细介绍,下面将介绍额外的功能特性
鉴权
对于许多公司的api,通常需要鉴权,大部分鉴权系统是通过http/grpc的header携带token,dtm支持全局事务范围的header自定义,详细的使用,可以参考 事务选项中自定义header部分
单服务多数据源
部分应用服务,会访问多个数据源,当他们组成全局事务时,需要做到多个数据源的事务,要么都成功,要么都回滚。大多数分布式事务框架,未提供这种支持,而 dtm 可以通过简单的技巧支持
假定现在跨行转账时,不需要跨服务,只需要跨数据库修改数据,那么可以将两个事务分支,合并为一个事务分支,然后在一个服务内,跨数据源操作数据。
app.POST(BusiAPI+"/SagaMultiSource", dtmutil.WrapHandler2(func(c *gin.Context) interface{} {
barrier := MustBarrierFromGin(c)
transOutSource := pdbGet() // 数据源1
err := barrier.CallWithDB(transOutSource, func(tx *sql.Tx) error {
return SagaAdjustBalance(tx, TransOutUID, -reqFrom(c).Amount, reqFrom(c).TransOutResult)
})
if err != nil {
return err
}
transInSource := pdbGet() // 数据源2
return MustBarrierFromGin(c).CallWithDB(transInSource, func(tx *sql.Tx) error {
return SagaAdjustBalance(tx, TransInUID, reqFrom(c).Amount, reqFrom(c).TransInResult)
})
}))
app.POST(BusiAPI+"/SagaMultiSourceRevert", dtmutil.WrapHandler2(func(c *gin.Context) interface{} {
barrier := MustBarrierFromGin(c)
transInSource := pdbGet() // 数据源2
err := MustBarrierFromGin(c).CallWithDB(transInSource, func(tx *sql.Tx) error {
return SagaAdjustBalance(tx, TransInUID, -reqFrom(c).Amount, "")
})
if err != nil {
return err
}
transOutSource := pdbGet() // 数据源1
return barrier.CallWithDB(transOutSource, func(tx *sql.Tx) error {
return SagaAdjustBalance(tx, TransOutUID, +reqFrom(c).Amount, "")
})
}))
saga := dtmcli.NewSaga(dtmutil.DefaultHTTPServer, dtmcli.MustGenGid(dtmutil.DefaultHTTPServer)).
Add(busi.Busi+"/SagaMultiSource", busi.Busi+"/SagaMultiSourceRevert", req)
上述的代码能够保证,在各种异常情况下,数据源1和数据源2的数据修改,要么同时成功,要么同时回滚。
可运行的示例,参见dtm-examples中的 multiSource