日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
用Go輕松完成一個(gè)XA分布式事務(wù),保姆級(jí)教程

用GO輕松完成一個(gè)XA分布式事務(wù),保姆級(jí)教程

作者:佚名 2021-09-14 13:55:15

開(kāi)發(fā)

前端

分布式 如果一個(gè)事務(wù)涉及的所有操作能夠放在一個(gè)服務(wù)內(nèi)部,那么使用各門語(yǔ)言里事務(wù)相關(guān)的庫(kù),可以輕松的實(shí)現(xiàn)多個(gè)操作作為整體的事務(wù)操作。

事務(wù)

某些業(yè)務(wù)要求,一系列操作必須全部執(zhí)行,而不能僅執(zhí)行一部分。例如,一個(gè)轉(zhuǎn)賬操作:

  
 
 
 
  1. -- 從id=1的賬戶給id=2的賬戶轉(zhuǎn)賬100元 
  2. -- 第一步:將id=1的A賬戶余額減去100 
  3. UPDATE accounts SET balance = balance - 100 WHERE id = 1; 
  4. -- 第二步:將id=2的B賬戶余額加上100 
  5. UPDATE accounts SET balance = balance + 100 WHERE id = 2; 

這兩條SQL語(yǔ)句必須全部執(zhí)行,或者,由于某些原因,如果第一條語(yǔ)句成功,第二條語(yǔ)句失敗,就必須全部撤銷。

這種把多條語(yǔ)句作為一個(gè)整體進(jìn)行操作的功能,被稱為數(shù)據(jù)庫(kù)事務(wù)。數(shù)據(jù)庫(kù)事務(wù)可以確保該事務(wù)范圍內(nèi)的所有操作都可以全部 成功或者全部失敗。如果事務(wù)失敗,那么效果就和沒(méi)有執(zhí)行這些SQL一樣,不會(huì)對(duì)數(shù)據(jù)庫(kù)數(shù)據(jù)有任何改動(dòng)。

微服務(wù)

如果一個(gè)事務(wù)涉及的所有操作能夠放在一個(gè)服務(wù)內(nèi)部,那么使用各門語(yǔ)言里事務(wù)相關(guān)的庫(kù),可以輕松的實(shí)現(xiàn)多個(gè)操作作為整體的事務(wù)操作。

但是有些服務(wù),例如生成訂單涉及做很多操作,包括庫(kù)存、優(yōu)惠券、贈(zèng)送、賬戶余額等。當(dāng)系統(tǒng)復(fù)雜程度增加時(shí),想要把所有這些操作放到一個(gè)服務(wù)內(nèi)實(shí)現(xiàn),會(huì)導(dǎo)致耦合度太高,維護(hù)成本非常高。

針對(duì)復(fù)雜的系統(tǒng),當(dāng)前流行的微服務(wù)架構(gòu)是非常好的解決方案,該架構(gòu)能夠把復(fù)雜系統(tǒng)進(jìn)行拆分,拆分后形成了大量微服務(wù),獨(dú)立開(kāi)發(fā),獨(dú)立維護(hù)。

雖然服務(wù)拆分了,但是訂單本身的邏輯需要多個(gè)操作作為一個(gè)整體,要么全部成功,要么全部失敗,這就帶來(lái)了新的挑戰(zhàn)。如何把散落在各個(gè)微服務(wù)中的本地事務(wù),組成一個(gè)大的事務(wù),保證他們作為一個(gè)整體,這就是分布式事務(wù)需要解決的問(wèn)題。

分布式事務(wù)

分布式事務(wù)簡(jiǎn)單的說(shuō),就是一次大的操作由不同的小操作組成,這些小的操作分布在不同的服務(wù)器上,且屬于不同的應(yīng)用,分布式事務(wù)需要保證這些小操作要么全部成功,要么全部失敗。本質(zhì)上來(lái)說(shuō),分布式事務(wù)就是為了保證不同數(shù)據(jù)庫(kù)的數(shù)據(jù)一致性。

分布式事務(wù)方案包括:

  • xa
  • tcc
  • saga
  • 可靠消息

下面我們看看最簡(jiǎn)單的xa

XA

XA是由X/Open組織提出的分布式事務(wù)的規(guī)范,XA規(guī)范主要定義了(全局)事務(wù)管理器(TM)和(局部)資源管理器(RM)之間的接口。本地的數(shù)據(jù)庫(kù)如mysql在XA中扮演的是RM角色

XA一共分為兩階段:

第一階段(prepare):即所有的參與者RM準(zhǔn)備執(zhí)行事務(wù)并鎖住需要的資源。參與者ready時(shí),向TM報(bào)告已準(zhǔn)備就緒。 第二階段 (commit/rollback):當(dāng)事務(wù)管理者(TM)確認(rèn)所有參與者(RM)都ready后,向所有參與者發(fā)送commit命令。

目前主流的數(shù)據(jù)庫(kù)基本都支持XA事務(wù),包括mysql、oracle、sqlserver、postgre

我們看看本地?cái)?shù)據(jù)庫(kù)是如何支持XA的:

第一階段 準(zhǔn)備

  
 
 
 
  1. XA start '4fPqCNTYeSG' 
  2. UPDATE `user_account` SET `balance`=balance + 30,`update_time`='2021-06-09 11:50:42.438' WHERE user_id = '1' 
  3. XA end '4fPqCNTYeSG' 
  4. XA prepare '4fPqCNTYeSG' 
  5. -- 當(dāng)所有的參與者完成了prepare,就進(jìn)入第二階段 提交 
  6. xa commit '4fPqCNTYeSG' 

xa實(shí)踐

介紹了這么多,我們來(lái)實(shí)踐完成一個(gè)微服務(wù)上的xa事務(wù),加深分布式事務(wù)的理解,這里采用dtm作為分布式事務(wù)的管理者,來(lái)運(yùn)行其中一個(gè)xa的demo

安裝go 安裝mysql

獲取dtm

  
 
 
 
  1. git clone https://github.com/yedf/dtm.git 
  2. cd dtm 

配置mysql

  
 
 
 
  1. cp conf.sample.yml conf.yml 
  2. vi conf.yml 

運(yùn)行示例

go run app/main.go xa

從日志里,能夠找到XA部分的輸出,最后成功提交完成了事務(wù)

  
 
 
 
  1. # 服務(wù)1輸出 
  2. XA start '4fPqCNTYeSG' 
  3. UPDATE `user_account` SET `balance`=balance - 30,`update_time`='2021-06-09 11:50:42.438' WHERE user_id = '1' 
  4. XA end '4fPqCNTYeSG' 
  5. XA prepare '4fPqCNTYeSG' 
  6.  
  7. # 服務(wù)2輸出 
  8. XA start '4fPqCPijxyC' 
  9. UPDATE `user_account` SET `balance`=balance + 30,`update_time`='2021-06-09 11:50:42.493' WHERE user_id = '2' 
  10. XA end '4fPqCPijxyC' 
  11. XA prepare '4fPqCPijxyC' 
  12.  
  13. # 服務(wù)1輸出 
  14. xa commit '4fPqCNTYeSG' 
  15.  
  16. #服務(wù)2輸出 
  17. xa commit '4fPqCPijxyC' 

整個(gè)交互的時(shí)序詳情如下

代碼如下:

  
 
 
 
  1. // 微服務(wù)的處理函數(shù): 
  2. app.POST(BusiAPI+"/TransInXa", common.WrapHandler(func(c *gin.Context) (interface{}, error) { 
  3.     return XaClient.XaLocalTransaction(c.Request.URL.Query(), func(db *sql.DB, xa *dtmcli.Xa) (interface{}, error) { 
  4.         _, err := dtmcli.DBExec(db, "update dtm_busi.user_account set balance=balance+? where user_id=?", reqFrom(c).Amount, 2) 
  5.         return dtmcli.MapSuccess, err 
  6.     }) 
  7. })) 
  8. app.POST(BusiAPI+"/TransOutXa", common.WrapHandler(func(c *gin.Context) (interface{}, error) { 
  9.     return XaClient.XaLocalTransaction(c.Request.URL.Query(), func(db *sql.DB, xa *dtmcli.Xa) (interface{}, error) { 
  10.         _, err := dtmcli.DBExec(db, "update dtm_busi.user_account set balance=balance-? where user_id=?", reqFrom(c).Amount, 1) 
  11.         return dtmcli.MapSuccess, err 
  12.     }) 
  13. })) 
  14.  
  15. // 開(kāi)啟XA事務(wù) 
  16. err := XaClient.XaGlobalTransaction(gid, func(xa *dtmcli.Xa) (*resty.Response, error) { 
  17.     resp, err := xa.CallBranch(&TransReq{Amount: 30}, Busi+"/TransOutXa") 
  18.     if err != nil { 
  19.         return resp, err 
  20.     } 
  21.     return xa.CallBranch(&TransReq{Amount: 30}, Busi+"/TransInXa") 
  22. }) 

總結(jié)

至此,一個(gè)完整的xa分布式事務(wù)介紹完成。

關(guān)于分布式事務(wù)更多更全面的知識(shí),請(qǐng)參考 分布式事務(wù)最經(jīng)典的七種解決方案

在這篇簡(jiǎn)短的文章里,我們大致介紹了 事務(wù),分布式事務(wù),微服務(wù)處理XA事務(wù)。有興趣的同學(xué)可以通過(guò) dtm 繼續(xù)研究分布式事務(wù)。


網(wǎng)頁(yè)標(biāo)題:用Go輕松完成一個(gè)XA分布式事務(wù),保姆級(jí)教程
文章鏈接:http://www.dlmjj.cn/article/cdescsp.html