過來人的經(jīng)驗,談談一致性處理方案—分布式事務(DTS)

轉載自己該篇文章的微信版本鏈接

文章摘要:原來大型分布式/微服務系統(tǒng)中解決數(shù)據(jù)一致性問題,居然是通過……

一溉潭、為什么要使用分布式事務—2PC净响?

傳統(tǒng)事務是使用數(shù)據(jù)庫自身的事務屬性(ACID),而數(shù)據(jù)庫自身的事務屬性是局限于當前實例喳瓣,不能實現(xiàn)跨庫馋贤。而對于大型分布式/微服務集群系統(tǒng)中,不僅存在著跨庫的事務畏陕,還存在很多不同系統(tǒng)/服務之間的RPC調用配乓,這種調用往往也需要保證業(yè)務以及數(shù)據(jù)的一致性。因此蹭秋,有必要使用一種分布式事務框架來協(xié)調整個端到端業(yè)務調用鏈路的應用和數(shù)據(jù)庫來保證業(yè)務最終的數(shù)據(jù)一致性扰付,而目前在分布式事務中用的比較多的即為基于所有服務參與者投票的二階段協(xié)議(2PC)。

二仁讨、分布式事務基礎模型

由于在大型SOA/微服務系統(tǒng)架構下羽莺,一次業(yè)務請求往往會跨越多個服務,多個服務共同協(xié)調完成一次端到端的全鏈路業(yè)務調用時洞豁,由于業(yè)務約束或者服務提供者的故障等原因造成多個系統(tǒng)中數(shù)據(jù)不一致或通信延遲等問題盐固,因此對于分布式/微服務系統(tǒng)中的多服務協(xié)調調用場景需要分布式事務來保證系統(tǒng)的ACID屬性。

1.X/Open DTP模型

目前二階段的分布式事務一般基于以下的X/Open

DTP(Distributed Transaction Processing Reference Model)丈挟。

其中刁卜,

AppService:是服務應用∈镅剩可以理解為使用分布式事務的應用程序蛔趴。

RM(Resource Manager):資源管理器。這里主要指的是服務應用通過資源管理器對數(shù)據(jù)庫或者消息隊列服務器這類資源進行控制例朱,資源需要實現(xiàn)XA接口孝情;

TM(Transaction Manager):事務管理器。負責協(xié)調和管理事務洒嗤,提供給服務應用編程接口管理上面的資源管理器箫荡。

AppService可以和TM、RM進行通信渔隶,TM和RM也能夠進行通信羔挡,服務應用可以通過TX接口向事務管理器發(fā)起事務、提交事務和回滾事務间唉。TM和RM通過XA接口進行雙向通信绞灼,比如TM通知RM提交事務或回滾事務;RM把提交結果通知給TM呈野。AppService和RM之間則通過RM提供的本地API接口進行資源控制镀赌。

2.分布式二階段提交協(xié)議

通常在一個全鏈路的端到端業(yè)務操作中,往往會跨多個節(jié)點际跪、多個應用商佛,為了能夠保證全局事務的ACID特性喉钢,需要引入一個協(xié)調組件(這里為TM)來控制所有服務參與者(這里為RM)的操作結果,根據(jù)所有參與者的反饋結果來決定整個分布式事務究竟是提交還是回滾的結果良姆。

第一階段:稱為準備(prepare)階段肠虽。事務協(xié)調者向各個服務應用發(fā)送prepare請求,服務應用在得到請求后做預處理操作玛追,預處理可能是做預檢查税课,也可能是把請求臨時存儲,可以理解為是一種試探性地提交痊剖。下面是一般的步驟:

a.事務協(xié)調者會問所有的參與者服務韩玩,是否可以提交操作。

b.各個參與者開始事務執(zhí)行的準備工作:如資源上鎖陆馁,預留資源找颓,寫回滾/重試的log。

c.參與者響應協(xié)調者叮贩,如果事務準備工作成功击狮,則回應“可以提交”,否則回應拒絕提交益老。

第二階段:稱為提交(commit)/回滾(rollback)階段彪蓬。是指事務真正提交或者回滾的階段。如果事務協(xié)調者發(fā)現(xiàn)事務參與者有一個在prepare階段出現(xiàn)失敗捺萌,則會要求所有的參與者進行回滾档冬。如果協(xié)調者發(fā)現(xiàn)所有的參與者都prepare操作都是成功,那么他將向所有的參與者發(fā)出提交請求桃纯,這時所有參與者才會正式提交酷誓。由此保證了要求全部提交成功,要么全部失敗慈参。下面是具體步驟:

a.如果所有的參與者都回應“可以提交”呛牲,那么協(xié)調者向所有參與者發(fā)送“正式提交”的命令刮萌。參與者完成正式提交驮配,并釋放所有資源,然后回應“完成”着茸,協(xié)調者收集各個服務的“完成”回應后結束事務壮锻。

b.如果有一個參與者回應“拒絕提交”,那么協(xié)調者向所有的參與者發(fā)送“回滾操作”涮阔,并釋放所有的資源猜绣,然后回應“回滾完成”,協(xié)調者收集各個服務應用的“回滾”返回后敬特,取消整體的分布式事務掰邢。

下圖為二階段的成功和失敗示例圖:

三牺陶、分布式事務—2PC的基本概念&&主要執(zhí)行流程

下面先用一張框圖來大致描述下分布式事務DTS,二階段提交是如何執(zhí)行的:

上面的圖中是以訂單支付來舉例的辣之。圖中的業(yè)務核心這里主要指的訂單系統(tǒng)(訂單系統(tǒng)作為大型微服務系統(tǒng)中的一個服務本身并不具備支付的服務能力掰伸,因此需要調用其他或者第三方的賬務計費系統(tǒng)完成支付以及結算業(yè)務),在這里它發(fā)起分布式事務怀估,需要調用賬務系統(tǒng)以完成訂單支付業(yè)務活動狮鸭。DTS協(xié)調者實際上即為DTS Server,它會統(tǒng)一協(xié)調參與分布式事務的各個參與者之間提交/回滾多搀。

1.事務發(fā)起者與參與者

在本文的上篇中歧蕉,只是將分布式系統(tǒng)中所有服務稱之為參與者。由于二階段提交的“準備”操作實現(xiàn)復雜性和效率都會在實際的業(yè)務中產(chǎn)生影響康铭,因此需要引入一個簡單的優(yōu)化惯退,在模型中將事務將有一個參與者不參與二段提交的過程(稱為單階段參與者),而是在其余二階段參與者都準備好后麻削,再請求單階段參與者提交蒸痹,單階段參與者的提交結果將決定整個分布式事務的結果。如果單階段參與者提交成功呛哟,那么協(xié)調者要求其余參與者都提交叠荠,如果提交失敗則協(xié)調者要求其余參與者都事務回滾。這里的單階段參與者也即為下文所述的事務發(fā)起方扫责。

在二階段的分布式事務中榛鼎,事務發(fā)起者又稱為發(fā)起方,它是整個業(yè)務活動的主體鳖孤、是服務的編排者者娱,由它啟動業(yè)務活動并決定業(yè)務活動提交或回滾。簡單的例子如上圖中苏揣,業(yè)務核心可以是訂單中心等黄鳍,它需要調用賬務計費服務完成支付功能,那么此時它是發(fā)起分布式事務活動的發(fā)起方平匈,它命令其他系統(tǒng)協(xié)助完成一次完整的分布式事務框沟。那么參與到這一次分布式事務中來的其他系統(tǒng)就稱為參與者,這里賬務計費服務就是參與者增炭,它協(xié)助發(fā)起方完成相應的動作忍燥,執(zhí)行具體的業(yè)務邏輯。

下面給出兩個定義:

(1)Activity:把整個分布式事務稱為一次主業(yè)務活動(Activity)

(2)Action::把參與者的一次方法調用稱為原子活動(Action)

分布式事務必須確保各個角色的一致性和有效性隙姿,因此要保證框架進行提交或者回滾梅垄,Activity和Action,必須在分布式事務執(zhí)行階段將狀態(tài)等信息記錄下來输玷,如果這些信息只記錄在內存或者本地存儲中队丝,該中記錄方式容錯性低靡馁,無法應付宕機等問題,因此這些狀態(tài)信息記錄在DB中机久,通過建立分布式業(yè)務控制活動主表(business_activity)來記錄全局事務的活動狀態(tài)奈嘿,以及原子業(yè)務活動表(business_action)來記錄原子業(yè)務活動的狀態(tài)。在開始一個分布式事務的時候框架先創(chuàng)建activity主活動記錄吞加,每調用一個參與者就會再創(chuàng)建一個action原子活動記錄裙犹。

2.分布式事務中的同庫/異庫模式

這里可以根據(jù)業(yè)務控制活動主表記錄(簡稱為activity)和原子業(yè)務活動表(簡稱為action)記錄是否保存在業(yè)務庫還是中DTS

Server庫,分為以下兩種情況:

(1)同庫模式

發(fā)起方會在自己業(yè)務庫的事務模板(transactionTemplate)中開起分布式事務衔憨,并且將上述的business_activity/business_action存儲在業(yè)務庫中叶圃,由于DB的插入操作相對較快且無需額外的RPC調用,因此適合業(yè)務量比較大的業(yè)務場景践图。但需要進行額外的編程配置掺冠,比如配置數(shù)據(jù)源、事務模板码党、DAO等德崭。

(2)異庫模式

發(fā)起方會在自己業(yè)務庫的事務模板中開起分布式事務,而business_activity/business_activity這兩個表會存儲在DTS Server這個中間協(xié)調者的數(shù)據(jù)庫內揖盘,即為這兩個表和業(yè)務表不同庫眉厨。該模式下,通常需要RPC調用DTS Server查詢數(shù)據(jù)庫的元數(shù)據(jù)兽狭。適用業(yè)務量較小的場景憾股。但是分布式活動方便集中管理,管理方便易于排查問題箕慧。

同庫模式和異庫模式存在的原因是必須記錄主事務的信息到DB中服球,方便提交/回滾以及recover(如果是同庫模式,主要是recovery颠焦,如果是異庫模式就是提交/回滾+recovery),確保各系統(tǒng)之間的一致性斩熊,但是由于分布式事務中必然存在一些外圍系統(tǒng)接入而且根據(jù)業(yè)務情況無法保證數(shù)據(jù)表總是存放在本地庫中,因此產(chǎn)生了該兩種模式伐庭。

同樣對于整個調用鏈路中的服務應用參與者來說也可以分為以下兩種情況:

(1)local模式

事務元數(shù)據(jù)Action記錄在本地和Activity同庫粉渠,且沒有直接remote參與者,發(fā)起方在本地對參與者發(fā)起提交/回滾似忧。原子活動記錄Action和Activity都是同庫渣叛,速度比較快丈秩。但是盯捌,原子活動的context內容由框架獲取預處理階段提交的參數(shù)無法修改。

(2)remote模式

沒有配置本地數(shù)據(jù)源蘑秽,Activity和Action的記錄都存在DTSServer中饺著,整個回滾和提交過程將由中間協(xié)調者DTS Server來完成箫攀。該種模式的優(yōu)點在于可以自行創(chuàng)建原子活動記錄,能夠控制context內容幼衰;可以啟動嵌套的分布式事務靴跛。然而缺點也比較明顯,創(chuàng)建原子活動記錄需要手動觸發(fā)渡嚣,記錄由遠程服務存儲梢睛,效率比較低。

由于在大型分布式/微服務應用中识椰,實際生產(chǎn)環(huán)境中的業(yè)務量往往較大绝葡,綜合考慮性能、穩(wěn)定性等因素腹鹉,因此通常會使用發(fā)起方同庫+服務參與者local/remote模式藏畅。

3.發(fā)起方和參與者的具體執(zhí)行流程

限于篇幅,下面分別通過兩幅框圖來說明發(fā)起方同庫模式下功咒,服務參與方存在local和remote模式的業(yè)務調用場景愉阎。

(1)一階段:在訂單中心(業(yè)務核心)這個分布式事務發(fā)起方開啟事務模塊,將Activity記錄插入至本地業(yè)務庫的分布式業(yè)務控制活動主表(business_activity)中力奋,對參與者——賬務計費系統(tǒng)發(fā)起事務時榜旦,如果參與者服務響應OK,則攔截器將自動將Action記錄插入至本地的原子業(yè)務活動表(business_action)中景殷。

(2)二階段:在正常的情況下章办,發(fā)起方直接向參與者提交/回滾操作。

(1)一階段:在該模式下滨彻,Activity記錄在發(fā)起方本地藕届,此時參與者服務是remote模式,需要參與者自己向DTS Server注冊分支事務(即為在DTS Server的庫中插入action記錄)亭饵。

(2)二階段:發(fā)起方事務先向DTS Server發(fā)送提交/回滾操作休偶,然后DTS Server再向參與者發(fā)起提交/回滾操作。

4.分布式事務的異常處理流程

任何系統(tǒng)設計都需要考慮服務故障辜羊、服務器宕機踏兜、網(wǎng)絡通信延遲以及數(shù)據(jù)庫不可用等外部因素。上面只是對分布式事務正常的執(zhí)行流程和原理進行了闡述八秃,那如果在事務執(zhí)行中碱妆,一階段失敗回滾的時候,恰好系統(tǒng)服務故障導致回滾不成功昔驱;或者二階段提交時候疹尾,系統(tǒng)服務故障導致提交不成功,那么如何來保證一致性呢?在這里我們可以考慮在分布式事務協(xié)調者的DTS Server中設計一套異衬杀荆恢復機制來對進行容錯和恢復窍蓝。

可以清楚看到,如果狀態(tài)為U繁成,表明有可能是異庫模式下的主活動記錄吓笙,這時并不清楚當前事務到底執(zhí)行到何種狀態(tài),是否是確認提交或者確認回滾巾腕,那么需要對進行回查處理面睛,需要我們自己來寫回查代碼,將回查的結果返回尊搬。如果是DONE侮穿,表明一階段完成,此時對應的是確認提交狀態(tài)亲茅,應為C;如果為NOT_DONE克锣,那么表明一階段失敗,對應了確認回滾狀態(tài)腔长,應為I。然后再調用對應的二階段的提交/回滾就即可捞附。如果撈取出來狀態(tài)為I/C,就直接進行回滾/提交鸟召。

DTS Server中有一個異车ò恚恢復的recover線程在運行欧募,每隔1分鐘就去Activity記錄所在的DB撈取記錄,如果這是狀態(tài)被記錄為異常狀態(tài),那么recover程序就會嘗試恢復被中斷的事務,也就是重試,直到二階段事務成功提交/回滾事務娱两。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市金吗,隨后出現(xiàn)的幾起案子十兢,更是在濱河造成了極大的恐慌趣竣,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纪挎,死亡現(xiàn)場離奇詭異,居然都是意外死亡跟匆,警方通過查閱死者的電腦和手機异袄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來玛臂,“玉大人烤蜕,你說我怎么就攤上這事〖T” “怎么了讽营?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長泡徙。 經(jīng)常有香客問我橱鹏,道長,這世上最難降的妖魔是什么堪藐? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任莉兰,我火速辦了婚禮,結果婚禮上礁竞,老公的妹妹穿的比我還像新娘糖荒。我一直安慰自己,他們只是感情好模捂,可當我...
    茶點故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布捶朵。 她就那樣靜靜地躺著,像睡著了一般狂男。 火紅的嫁衣襯著肌膚如雪综看。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天岖食,我揣著相機與錄音寓搬,去河邊找鬼。 笑死县耽,一個胖子當著我的面吹牛句喷,可吹牛的內容都是我干的。 我是一名探鬼主播兔毙,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼唾琼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了澎剥?” 一聲冷哼從身側響起锡溯,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎祭饭,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體倡蝙,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡寺鸥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了烤低。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片笆载。...
    茶點故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖檐蚜,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情闯第,我是刑警寧澤,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布咳短,位于F島的核電站咙好,受9級特大地震影響,放射性物質發(fā)生泄漏勾效。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一层宫、第九天 我趴在偏房一處隱蔽的房頂上張望其监。 院中可真熱鬧,春花似錦毁菱、人聲如沸米死。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至捉邢,卻和暖如春商膊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背晕拆。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吝镣,地道東北人。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓末贾,卻偏偏與公主長得像整吆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子拴测,可洞房花燭夜當晚...
    茶點故事閱讀 43,554評論 2 349

推薦閱讀更多精彩內容