go-zero 分佈式事務最佳實踐

背景

隨着業務的快速發展、業務複雜度越來越高,微服務作爲最佳解決方案之一,它解耦服務,降低複雜度,增加可維護性的同時,也帶來一部分新問題。

當我們需要跨服務保證數據一致性時,原先的數據庫事務力不從心,無法將跨庫、跨服務的多個操作放在一個事務中。這樣的應用場景非常多,我們可以列舉出很多:

面對這些本地事務無法解決的場景,我們需要分佈式事務的解決方案,保證跨服務、跨數據庫更新數據的一致性。

go-zero 與 dtm 強強聯合,推出了在 go-zero 中無縫接入 dtm 的極簡方案,讓分佈式事務的使用從未如此簡單。

運行一個例子

我們來看一個可運行的例子,然後再看如何自己開發完成一個完整的分佈式事務

下面以 etcd 作爲註冊服務中心,可以按照如下步驟運行一個 go-zero 的示例:

MicroService:
    Driver: 'dtm-driver-gozero' # 配置dtm使用go-zero的微服務協議
    Target: 'etcd://localhost:2379/dtmservice' # 把dtm註冊到etcd的這個地址
    EndPoint: 'localhost:36790' # dtm的本地地址
# 前提:已安裝etcd
etcd
# 前提:已配置好dtm的數據庫鏈接
go run app/main.go dev
git clone github.com/yedf/dtmdriver-clients && cd dtmdriver-clients
cd gozero/trans && go run trans.go
# 在dtmdriver-clients的目錄下
cd gozero/app && go run main.go

當你在 trans 的日誌中看到

2021/12/03 15:44:05 transfer out 30 cents from 1
2021/12/03 15:44:05 transfer in 30 cents to 2
2021/12/03 15:44:05 transfer out 30 cents from 1
2021/12/03 15:44:05 transfer out 30 cents from 1

那就是事務正常完成了

開發接入

參考 yedf/dtmdriver-clients 的代碼

// 下面這行導入gozero的dtm驅動
import _ "github.com/yedf/dtmdriver-gozero"

// 使用dtm的客戶端dtmgrpc之前,需要執行下面這行調用,告知dtmgrpc使用gozero的驅動來如何處理gozero的url
err := dtmdriver.Use("dtm-driver-gozero")
// check err

// dtm已經通過前面的配置,註冊到下面這個地址,因此在dtmgrpc中使用該地址
var dtmServer = "etcd://localhost:2379/dtmservice"

// 下面從配置文件中Load配置,然後通過BuildTarget獲得業務服務的地址
var c zrpc.RpcClientConf
conf.MustLoad(*configFile, &c)
busiServer, err := c.BuildTarget()

  // 使用dtmgrpc生成一個消息型分佈式事務並提交
 gid := dtmgrpc.MustGenGid(dtmServer)
 msg := dtmgrpc.NewMsgGrpc(dtmServer, gid).
    // 事務的第一步爲調用trans.TransSvcClient.TransOut
    // 可以從trans.pb.go中找到上述方法對應的Method名稱爲"/trans.TransSvc/TransOut"
    // dtm需要從dtm服務器調用該方法,所以不走強類型,而是走動態的url: busiServer+"/trans.TransSvc/TransOut"
  Add(busiServer+"/trans.TransSvc/TransOut"&busi.BusiReq{Amount: 30, UserId: 1}).
  Add(busiServer+"/trans.TransSvc/TransIn"&busi.BusiReq{Amount: 30, UserId: 2})
 err := msg.Submit()

整個開發接入的過程很少,前面的註釋已經很清晰,就不再贅述了。

注意事項

在開發接入的過程中,去找 *.pb.go 的文件中的 grpc 訪問的方法路徑時候,一定要找 invoke 的路徑

深入理解動態調用

在 go-zero 使用 dtm 的分佈式事務時,許多的調用是從 dtm 服務器發起的,例如 TCC 的 Confirm/CancelSAGA/MSG 的所有調用。

dtm 無需知道組成分佈式事務的相關業務 api 的強類型,它是動態的調用這些 api。

grpc 的調用,可以類比於 HTTP 的 POST,其中:

通過下面這部分代碼,dtm 就拿到了完整信息,就能夠發起完整的調用了

Add(busiServer+"/trans.TransSvc/TransOut", &busi.BusiReq{Amount: 30, UserId: 1})

更加完整的例子

熱心的社區同學 Mikael 幫忙寫了一個內容更加豐富的例子,結合實際應用和子事務屏障,完整的演示了一個線上實際運行的分佈式事務,有興趣的同學可以參考:

https://github.com/Mikaelemmmm/gozerodtm

其他方式接入

go-zero 的微服務還有非 etcd 的其他方式,我們依次說明他們的接入方式

直連

對於直連這種方式,您只需要在上面 dtmetcd 配置基礎上,將 Target 設置爲空字符串即可。

直連的情況,不需要將 dtm 註冊到註冊中心。

K8S

對於 K8S 這種方式,您只需要在上面 dtmetcd 配置基礎上,將 Target 設置爲空字符串即可。

K8S 中,將服務註冊到 K8S 中,是由 deployment.yaml 完成的,應用內部,不需要進行註冊。

直播分享預告

go-zero 作者和我(dtm 作者)將在 12 月 22 日晚 21 點,在 Go 夜讀,聯合做一場《go-zero 的分佈式事務實踐》的直播分享,將會帶來更多更深入的討論。歡迎大家屆時參加。

直播地址爲:https://live.bilibili.com/11171965

小結

這一次 go-zerodtm 的合作,在 go 生態中,打造了首個原生支持分佈式事務的微服務解決方案,意義重大。

歡迎大家使用 go-zerodtm,使用我們原生的 分佈式事務的微服務解決方案,並 star 支持我們!


本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/1hUhSRkWFqFnO6w1PasrGw