更多功能特性
大部分的功能特性,已经在相关的文档里详细介绍,下面将介绍额外的功能特性
鉴权
对于许多公司的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