更多功能特性

大部分的功能特性,已经在相关的文档里详细介绍,下面将介绍额外的功能特性

鉴权

对于许多公司的api,通常需要鉴权,大部分鉴权系统是通过http/grpc的header携带token,dtm支持全局事务范围的header自定义,详细的使用,可以参考 事务选项中自定义header部分

单服务多数据源

部分应用服务,会访问多个数据源,当他们组成全局事务时,需要做到多个数据源的事务,要么都成功,要么都回滚。大多数分布式事务框架,未提供这种支持,而 dtm 可以通过简单的技巧支持

假定现在跨行转账时,不需要跨服务,只需要跨数据库修改数据,那么可以将两个事务分支,合并为一个事务分支,然后在一个服务内,跨数据源操作数据。

  1. app.POST(BusiAPI+"/SagaMultiSource", dtmutil.WrapHandler2(func(c *gin.Context) interface{} {
  2. barrier := MustBarrierFromGin(c)
  3. transOutSource := pdbGet() // 数据源1
  4. err := barrier.CallWithDB(transOutSource, func(tx *sql.Tx) error {
  5. return SagaAdjustBalance(tx, TransOutUID, -reqFrom(c).Amount, reqFrom(c).TransOutResult)
  6. })
  7. if err != nil {
  8. return err
  9. }
  10. transInSource := pdbGet() // 数据源2
  11. return MustBarrierFromGin(c).CallWithDB(transInSource, func(tx *sql.Tx) error {
  12. return SagaAdjustBalance(tx, TransInUID, reqFrom(c).Amount, reqFrom(c).TransInResult)
  13. })
  14. }))
  15. app.POST(BusiAPI+"/SagaMultiSourceRevert", dtmutil.WrapHandler2(func(c *gin.Context) interface{} {
  16. barrier := MustBarrierFromGin(c)
  17. transInSource := pdbGet() // 数据源2
  18. err := MustBarrierFromGin(c).CallWithDB(transInSource, func(tx *sql.Tx) error {
  19. return SagaAdjustBalance(tx, TransInUID, -reqFrom(c).Amount, "")
  20. })
  21. if err != nil {
  22. return err
  23. }
  24. transOutSource := pdbGet() // 数据源1
  25. return barrier.CallWithDB(transOutSource, func(tx *sql.Tx) error {
  26. return SagaAdjustBalance(tx, TransOutUID, +reqFrom(c).Amount, "")
  27. })
  28. }))
  29. saga := dtmcli.NewSaga(dtmutil.DefaultHTTPServer, dtmcli.MustGenGid(dtmutil.DefaultHTTPServer)).
  30. Add(busi.Busi+"/SagaMultiSource", busi.Busi+"/SagaMultiSourceRevert", req)

上述的代码能够保证,在各种异常情况下,数据源1和数据源2的数据修改,要么同时成功,要么同时回滚。

可运行的示例,参见dtm-examples中的 multiSource