1 背景知識(shí)
隨著業(yè)務(wù)的快速發(fā)展、業(yè)務(wù)復(fù)雜度越來(lái)越高,幾乎每個(gè)公司的系統(tǒng)都會(huì)從單體走向分布式,特別是轉(zhuǎn)向微服務(wù)架構(gòu)。
隨之而來(lái)就必然遇到分布式事務(wù)這個(gè)難題,這篇文章通過(guò) seata 框架總結(jié)了分布式事務(wù)的幾種解決方案
1.1 ACID
關(guān)系型數(shù)據(jù)庫(kù)具有解決復(fù)雜事務(wù)場(chǎng)景的能力,關(guān)系型數(shù)據(jù)庫(kù)的事務(wù)滿足 ACID 的特性。
Atomicity:原子性(要么都做,要么都不做)
Consistency:一致性(數(shù)據(jù)庫(kù)只有一個(gè)狀態(tài),不存在未確定狀態(tài))
Isolation:隔離性(事務(wù)之間互不干擾)
Durability:永久性(事務(wù)一旦提交,數(shù)據(jù)庫(kù)記錄永久不變)
1.2 CAP
CAP 是指在一個(gè)分布式系統(tǒng)下, 包含三個(gè)要素:Consistency(一致性)、Availability(可用性)、Partition tolerance(分區(qū)容錯(cuò)性),并且三者不可得兼。
C:Consistency,一致性,所有數(shù)據(jù)變動(dòng)都是同步的。
A:Availability,可用性,即在可以接受的時(shí)間范圍內(nèi)正確地響應(yīng)用戶請(qǐng)求。
P:Partition tolerance,分區(qū)容錯(cuò)性,即某節(jié)點(diǎn)或網(wǎng)絡(luò)分區(qū)故障時(shí),系統(tǒng)仍能夠提供滿足一致性和可用性的服務(wù)。
1.3 BASE
BASE 理論主要是解決 CAP 理論中分布式系統(tǒng)的可用性和一致性不可兼得的問(wèn)題。BASE 理論包含以下三個(gè)要素:
BA:Basically Available,基本可用。
S:Soft State,軟狀態(tài),狀態(tài)可以有一段時(shí)間不同步。
E:Eventually Consistent,最終一致,最終數(shù)據(jù)是一致的就可以了,而不是時(shí)時(shí)保持強(qiáng)一致。
2 實(shí)現(xiàn)模式
2.1 二段提交
第一階段(準(zhǔn)備階段)
TM 通知所有參與事務(wù)的各個(gè) RM,給每個(gè) RM 發(fā)送 prepare 消息。
RM 接收到消息后進(jìn)入準(zhǔn)備階段后,要么直接返回失敗,要么創(chuàng)建并執(zhí)行本地事務(wù),寫本地事務(wù)日志(redo 和 undo 日志),但是不提交(此處只保留最后一步耗時(shí)最少的提交操作給第二階段執(zhí)行)。
第二階段(提交 / 回滾階段)
Seata 框架 基于兩階段提交模式,從設(shè)計(jì)上我們可以將整體分成三個(gè)大模塊,即 TM、RM、TC,具體解釋如下:
TM (Transaction Manager):全局事務(wù)管理器,控制全局事務(wù)邊界,負(fù)責(zé)全局事務(wù)開啟、全局提交、全局回滾。
RM (Resource Manager):資源管理器,控制分支事務(wù),負(fù)責(zé)分支注冊(cè)、狀態(tài)匯報(bào),并接收事務(wù)協(xié)調(diào)器的指令,驅(qū)動(dòng)分支(本地)事務(wù)的提交和回滾。
TC (Transaction Coordinator):事務(wù)協(xié)調(diào)器,維護(hù)全局事務(wù)的運(yùn)行狀態(tài),負(fù)責(zé)協(xié)調(diào)并驅(qū)動(dòng)全局事務(wù)的提交或回滾。
一個(gè)典型的分布式事務(wù)過(guò)程:
TM 向 TC 申請(qǐng)開啟一個(gè)全局事務(wù),全局事務(wù)創(chuàng)建成功并生成一個(gè)全局唯一的 XID。
XID 在微服務(wù)調(diào)用鏈路的上下文中傳播。
RM 向 TC 注冊(cè)分支事務(wù),將其納入 XID 對(duì)應(yīng)全局事務(wù)的管轄。
TM 向 TC 發(fā)起針對(duì) XID 的全局提交或回滾決議。
TC 調(diào)度 XID 下管轄的全部分支事務(wù)完成提交或回滾請(qǐng)求。
2.2 XA
在 XA 模式下,每一個(gè) XA 事務(wù)都是一個(gè)事務(wù)參與者。分布式事務(wù)開啟之后 首先在一階段執(zhí)行 “xa start”、“業(yè)務(wù) SQL”、“xa end” 和 “xa prepare” 完成 XA 事務(wù)的執(zhí)行和預(yù)提交; 二階段如果提交的話就執(zhí)行 “xa commit”,如果是回滾則執(zhí)行 “xa rollback”。這樣便能保證所有 XA 事務(wù)都提交或者都回滾。
無(wú)論 Phase2 的決議是 commit 還是 rollback,事務(wù)性資源的鎖都要保持到 Phase2 完成才釋放。
一個(gè)正常運(yùn)行的業(yè)務(wù),大概率是 90% 以上的事務(wù)最終應(yīng)該是成功提交的,我們是否可以在 Phase1 就將本地事務(wù)提交呢?
這樣 90% 以上的情況下,可以省去 Phase2 持鎖的時(shí)間,整體提高效率。
分支事務(wù)中數(shù)據(jù)的本地鎖由本地事務(wù)管理,在分支事務(wù) Phase1 結(jié)束時(shí)釋放,這時(shí)候其他本地事務(wù)就能讀取到最新的數(shù)據(jù)。
- 同時(shí),隨著本地事務(wù)結(jié)束,連接也得以釋放。
- 分支事務(wù)中數(shù)據(jù)的全局鎖在事務(wù)協(xié)調(diào)器管理,在決議 Phase2 全局提交時(shí),全局鎖馬上可以釋放,注意這里是先釋放鎖,再進(jìn)行分支事務(wù)的提交過(guò)程。
只有在決議全局回滾的情況下,全局鎖才被持有至分支的 Phase2 結(jié)束,即所有分支事務(wù)回滾結(jié)束。
這個(gè)設(shè)計(jì),極大地減少了分支事務(wù)對(duì)資源(數(shù)據(jù)和連接)的鎖定時(shí)間,給整體并發(fā)和吞吐的提升提供了基礎(chǔ)。但是分布式事務(wù)的隔離級(jí)別變化了
XA 模式和 下面的 AT 模式一樣是一種對(duì)業(yè)務(wù)無(wú)侵入性的解決方案;但與 AT 模式不同的是,XA 模式將快照數(shù)據(jù)和行鎖等通過(guò) XA 指令委托給了數(shù)據(jù)庫(kù)來(lái)完成,這樣 XA 模式實(shí)現(xiàn)更加輕量化
2.3 AT
AT 模式是一種無(wú)侵入的分布式事務(wù)解決方案。在 AT 模式下,用戶只需關(guān)注自己的 “業(yè)務(wù) SQL”,用戶的 “業(yè)務(wù) SQL” 就是全局事務(wù)一階段,Seata 框架會(huì)自動(dòng)生成事務(wù)的二階段提交和回滾操作。
一階段
首先,應(yīng)用要使用 Seata 的 JDBC 數(shù)據(jù)源代理,也就是前面提到的 RM 概念,所有對(duì) DB 的操作都是通過(guò) Seata RM 代理完成。
在這層代理中,Seata 會(huì)自動(dòng)控制 SQL 的執(zhí)行,提交,回滾。
Seata 代理會(huì)把業(yè)務(wù)數(shù)據(jù)在更新前后的數(shù)據(jù)鏡像 (beforeImage & afterImage) 組織成回滾日志,利用本地事務(wù)的 ACID 特性,將業(yè)務(wù)數(shù)據(jù)的更新和回滾日志的寫入在同一個(gè)本地事務(wù)中提交。
這樣,可以保證:任何提交的業(yè)務(wù)數(shù)據(jù)的更新一定有相應(yīng)的回滾日志存在。
然后,本地事務(wù)在提交之前,還需要通過(guò) RM 向 TC 注冊(cè)本地分支,這個(gè)注冊(cè)過(guò)程中會(huì)根據(jù)剛才執(zhí)行的 SQL 拿到所有涉及到的數(shù)據(jù)主鍵,以 resourceId + tableName + rowPK 作為鎖的 key,向 TC 申請(qǐng)所有涉及數(shù)據(jù)的寫鎖,當(dāng)獲得所有相關(guān)數(shù)據(jù)的寫鎖后,再執(zhí)行本地事務(wù)的 Commit 過(guò)程。
如果有任何一行數(shù)據(jù)的寫鎖沒有拿到的話,TC 會(huì)以 fastfail 的方式回復(fù)該 RM,RM 會(huì)以重試 + 超時(shí)機(jī)制重復(fù)該過(guò)程,直到超時(shí)。
完成本地事務(wù)后,RM 會(huì)向 TC 匯報(bào)本地事務(wù)的執(zhí)行情況,并完成業(yè)務(wù) RPC 的調(diào)用過(guò)程。
二階段
case1: 如果 TM 決議是全局提交,此時(shí)分支事務(wù)實(shí)際上已經(jīng)完成提交,TC 立刻釋放該全局事務(wù)的所有鎖,然后異步調(diào)用 RM 清理回滾日志,Phase2 可以非常快速地完成。
case2: 如果決議是全局回滾,RM 收到協(xié)調(diào)器發(fā)來(lái)的回滾請(qǐng)求,通過(guò) XID 和 Branch ID 找到相應(yīng)的回滾日志記錄,通過(guò)回滾記錄生成反向的更新 SQL 并執(zhí)行,以完成分支的回滾。
當(dāng)分支回滾順利結(jié)束時(shí),通知 TC 回滾完成,這時(shí)候 TC 才釋放該分支事務(wù)相關(guān)的所有鎖。
注:RM 在進(jìn)行回滾時(shí),會(huì)先跟 afterImage 進(jìn)行比較:
- 如果一致:則執(zhí)行逆向 SQL
- 如果不一致:再跟 beforeImage 進(jìn)行比較
- 如果一致:說(shuō)明沒必要執(zhí)行回滾 SQL 了,數(shù)據(jù)已經(jīng)恢復(fù)了
- 如果不一致:說(shuō)明出現(xiàn)了臟數(shù)據(jù),這時(shí)候就拋出異常,需要人工處理
2.4 TCC
TCC 模式需要用戶根據(jù)自己的業(yè)務(wù)場(chǎng)景實(shí)現(xiàn) Try、Confirm 和 Cancel 三個(gè)操作;事務(wù)發(fā)起方先在 TC 中注冊(cè)全局事務(wù),然后在一階段執(zhí)行 Try 方法,在二階段提交的話 TC 會(huì)去執(zhí)行各個(gè) RM 的 Confirm 方法,二階段回滾則 TC 會(huì)去執(zhí)行各個(gè) RM 的 Cancel 方法。
與 AT 模式一樣,Seata 會(huì)給實(shí)際方法的執(zhí)行加切面,該切面會(huì)攔截所有對(duì) TCC 接口的調(diào)用。
在調(diào)用 Try 接口時(shí),如果發(fā)現(xiàn)處在全局事務(wù)中,切面會(huì)先向 TC 注冊(cè)一個(gè)分支事務(wù),和 AT 不同的是 TCC 注冊(cè)分支事務(wù)是不加鎖的,注冊(cè)完成后去執(zhí)行原來(lái)的 RPC 調(diào)用。
當(dāng)請(qǐng)求鏈路調(diào)用完成后,TC 通過(guò)分支事務(wù)的資源 ID 回調(diào)到正確的參與者去執(zhí)行對(duì)應(yīng) TCC 資源的 Confirm 或 Cancel 方法。
TCC 模式的整體框架相對(duì)于 AT 來(lái)說(shuō)更加簡(jiǎn)單,主要是掃描 TCC 接口,注冊(cè)資源,攔截接口調(diào)用,注冊(cè)分支事務(wù),最后回調(diào)二階段接口。
最核心的實(shí)際上是 TCC 接口的實(shí)現(xiàn)邏輯。
1)使用原則
從 TCC 模型的框架可以發(fā)現(xiàn),TCC 模型的核心在于 TCC 接口的設(shè)計(jì)。用
戶在接入 TCC 時(shí),大部分工作都集中在如何實(shí)現(xiàn) TCC 服務(wù)上。
這就是 TCC 模式最主要的問(wèn)題,對(duì)業(yè)務(wù)侵入比較大,要花很大的功夫來(lái)實(shí)現(xiàn) TCC 服務(wù)。
設(shè)計(jì)一套 TCC 接口最重要的是什么?
主要有兩點(diǎn),第一點(diǎn),需要將操作分成兩階段完成。TCC(Try-Confirm-Cancel)分布式事務(wù)模型相對(duì)于 XA 等傳統(tǒng)模型,其特征在于它不依賴 RM 對(duì)分布式事務(wù)的支持,而是通過(guò)對(duì)業(yè)務(wù)邏輯的分解來(lái)實(shí)現(xiàn)分布式事務(wù)。
TCC 分布式事務(wù)模型需要業(yè)務(wù)系統(tǒng)提供三段業(yè)務(wù)邏輯:
1. 初步操作 Try:完成所有業(yè)務(wù)檢查,預(yù)留必須的業(yè)務(wù)資源。
2. 確認(rèn)操作 Confirm:真正執(zhí)行的業(yè)務(wù)邏輯,不做任何業(yè)務(wù)檢查,只使用 Try 階段預(yù)留的業(yè)務(wù)資源。因此,只要 Try 操作成功,Confirm 必須能成功。另外,Confirm 操作需滿足冪等性,保證一筆分布式事務(wù)能且只能成功一次。
3. 取消操作 Cancel:釋放 Try 階段預(yù)留的業(yè)務(wù)資源。同樣的,Cancel 操作也需要滿足冪等性。
因此,TCC 模型的隔離性思想就是通過(guò)業(yè)務(wù)的改造,在第一階段結(jié)束之后,從底層數(shù)據(jù)庫(kù)資源層面的加鎖過(guò)渡為上層業(yè)務(wù)層面的加鎖,釋放底層數(shù)據(jù)庫(kù)鎖資源,放寬分布式事務(wù)鎖協(xié)議,將鎖的粒度降到最低,以最大限度提高業(yè)務(wù)并發(fā)性能。
第二點(diǎn),就是要根據(jù)自身的業(yè)務(wù)模型去控制并發(fā),Seata 框架本身僅提供兩階段原子提交協(xié)議,保證分布式事務(wù)原子性。事務(wù)的隔離需要交給業(yè)務(wù)邏輯來(lái)實(shí)現(xiàn)。隔離的本質(zhì)就是控制并發(fā),防止并發(fā)事務(wù)操作相同資源而引起的結(jié)果錯(cuò)亂。例如:“賬戶 A 上有 100 元,事務(wù) T1 要扣除其中的 30 元,事務(wù) T2 也要扣除 30 元,出現(xiàn)并發(fā)”。
在第一階段 Try 操作中,需要先利用數(shù)據(jù)庫(kù)資源層面的加鎖,檢查賬戶可用余額,如果余額充足,則預(yù)留業(yè)務(wù)資源加到各自的凍結(jié)里,扣除本次交易金額,一階段結(jié)束后,雖然數(shù)據(jù)庫(kù)層面資源鎖被釋放了,但這筆資金被業(yè)務(wù)隔離,不允許除本事務(wù)之外的其它并發(fā)事務(wù)動(dòng)用。
2)異常控制
空回滾 空回滾就是對(duì)于一個(gè)分布式事務(wù),在沒有調(diào)用 TCC 資源 Try 方法的情況下,調(diào)用了二階段的 Cancel 方法,Cancel 方法需要識(shí)別出這是一個(gè)空回滾,然后直接返回成功。
Cancel 要識(shí)別出空回滾,直接返回成功。那關(guān)鍵就是要識(shí)別出這個(gè)空回滾。思路很簡(jiǎn)單就是需要知道一階段是否執(zhí)行,如果執(zhí)行了,那就是正常回滾;如果沒執(zhí)行,那就是空回滾。因此,需要一張額外的事務(wù)控制表,其中有分布式事務(wù) ID 和分支事務(wù) ID,第一階段 Try 方法里會(huì)插入一條記錄,表示一階段執(zhí)行了。
Cancel 接口里讀取該記錄,如果該記錄存在,則正常回滾;如果該記錄不存在,則是空回滾。 懸掛 懸掛就是對(duì)于一個(gè)分布式事務(wù),其二階段 Cancel 接口比 Try 接口先執(zhí)行。因?yàn)樵试S空回滾的原因,Cancel 接口認(rèn)為 Try 接口沒執(zhí)行,空回滾直接返回成功,對(duì)于 Seata 框架來(lái)說(shuō),認(rèn)為分布式事務(wù)的二階段接口已經(jīng)執(zhí)行成功,整個(gè)分布式事務(wù)就結(jié)束了。
但是這之后 Try 方法才真正開始執(zhí)行,預(yù)留業(yè)務(wù)資源,回想一下前面提到事務(wù)并發(fā)控制的業(yè)務(wù)加鎖,對(duì)于一個(gè) Try 方法預(yù)留的業(yè)務(wù)資源,只有該分布式事務(wù)才能使用,然而 Seata 框架認(rèn)為該分布式事務(wù)已經(jīng)結(jié)束,也就是說(shuō),當(dāng)出現(xiàn)這種情況時(shí),該分布式事務(wù)第一階段預(yù)留的業(yè)務(wù)資源就再也沒有人能夠處理了。
比如在 RPC 調(diào)用時(shí),先注冊(cè)分支事務(wù),再執(zhí)行 RPC 調(diào)用,如果此時(shí) RPC 調(diào)用的網(wǎng)絡(luò)發(fā)生擁堵,通常 RPC 調(diào)用是有超時(shí)時(shí)間的,RPC 超時(shí)以后,發(fā)起方就會(huì)通知 TC 回滾該分布式事務(wù),可能回滾完成后,RPC 請(qǐng)求才到達(dá)參與者,真正執(zhí)行,從而造成懸掛。
冪等
冪等就是對(duì)于同一個(gè)分布式事務(wù)的同一個(gè)分支事務(wù),重復(fù)去調(diào)用該分支事務(wù)的第二階段接口,因此,要求 TCC 的二階段 Confirm 和 Cancel 接口保證冪等,不會(huì)重復(fù)使用或者釋放資源。
如果冪等控制沒有做好,很有可能導(dǎo)致資損等嚴(yán)重問(wèn)題。
解決思路 Try 方法主要需要考慮兩個(gè)問(wèn)題,一個(gè)是 Try 方法需要能夠告訴二階段接口,已經(jīng)預(yù)留業(yè)務(wù)資源成功。第二個(gè)是需要檢查第二階段是否已經(jīng)執(zhí)行完成,如果已完成,則不再執(zhí)行 Confirm 方法。因?yàn)?Confirm 方法不允許空回滾,也就是說(shuō),Confirm 方法一定要在 Try 方法之后執(zhí)行。
因此,Confirm 方法只需要關(guān)注重復(fù)提交的問(wèn)題。需要一張事務(wù)執(zhí)行記錄表,可以先鎖定事務(wù)記錄,如果事務(wù)記錄為空,則說(shuō)明是一個(gè)空提交,不允許,終止執(zhí)行。如果事務(wù)記錄不為空,則繼續(xù)檢查狀態(tài)是否為初始化,如果是,則說(shuō)明一階段正確執(zhí)行,那二階段正常執(zhí)行即可。
如果狀態(tài)是已提交,則認(rèn)為是重復(fù)提交,直接返回成功即可;如果狀態(tài)是已回滾,也是一個(gè)異常,一個(gè)已回滾的事務(wù),不能重新提交,需要能夠攔截到這種異常情況,并報(bào)警。 Cancel 方法。因?yàn)?Cancel 方法允許空回滾,并且要在先執(zhí)行的情況下,讓 Try 方法感知到 Cancel 已經(jīng)執(zhí)行,所以和 Confirm 方法略有不同。
首先依然是鎖定事務(wù)記錄。如果事務(wù)記錄為空,則認(rèn)為 Try 方法還沒執(zhí)行,即是空回滾。空回滾的情況下,應(yīng)該先插入一條事務(wù)記錄,確保后續(xù)的 Try 方法不會(huì)再執(zhí)行。
如果插入成功,則說(shuō)明 Try 方法還沒有執(zhí)行,空回滾繼續(xù)執(zhí)行。如果插入失敗,則認(rèn)為 Try 方法正在執(zhí)行,等待 TC 的重試即可。
如果一開始讀取事務(wù)記錄不為空,則說(shuō)明 Try 方法已經(jīng)執(zhí)行完畢,再檢查狀態(tài)是否為初始化,如果是,則還沒有執(zhí)行過(guò)其他二階段方法,正常執(zhí)行 Cancel 邏輯。
如果狀態(tài)為已回滾,則說(shuō)明這是重復(fù)調(diào)用,允許冪等,直接返回成功即可。如果狀態(tài)為已提交,則同樣是一個(gè)異常,一個(gè)已提交的事務(wù),不能再次回滾
2.5 Saga
Saga 模式是 Seata 即將開源的長(zhǎng)事務(wù)解決方案。在 Saga 模式下,分布式事務(wù)內(nèi)有多個(gè)參與者,每一個(gè)參與者都是一個(gè)沖正補(bǔ)償服務(wù),需要用戶根據(jù)業(yè)務(wù)場(chǎng)景實(shí)現(xiàn)其正向操作和逆向回滾操作。
分布式事務(wù)執(zhí)行過(guò)程中,依次執(zhí)行各參與者的正向操作,如果所有正向操作均執(zhí)行成功,那么分布式事務(wù)提交。如果任何一個(gè)正向操作執(zhí)行失敗,那么分布式事務(wù)會(huì)去退回去執(zhí)行前面各參與者的逆向回滾操作,回滾已提交的參與者,使分布式事務(wù)回到初始狀態(tài)。
Saga 正向服務(wù)與補(bǔ)償服務(wù)也需要業(yè)務(wù)開發(fā)者實(shí)現(xiàn)。有點(diǎn)像是 TCC 模式將 Try 過(guò)程和 Confirm 過(guò)程合并,所有參與者直接執(zhí)行 Try + Confirm,如果有人失敗了,就反向依次 Cancel。
由于該模式主要用于長(zhǎng)事務(wù)場(chǎng)景,所以通常是由事件驅(qū)動(dòng)的,各個(gè)參與者之間是異步執(zhí)行的。
Saga 模式適用于業(yè)務(wù)流程長(zhǎng)且需要保證事務(wù)最終一致性的業(yè)務(wù)系統(tǒng),Saga 模式一階段就會(huì)提交本地事務(wù),無(wú)鎖、長(zhǎng)流程情況下可以保證性能 Saga 模式的優(yōu)勢(shì)是:
一階段提交本地?cái)?shù)據(jù)庫(kù)事務(wù),無(wú)鎖,高性能;
參與者可以采用事務(wù)驅(qū)動(dòng)異步執(zhí)行,高吞吐;
補(bǔ)償服務(wù)即正向服務(wù)的 “反向”,易于理解,易于實(shí)現(xiàn);
缺點(diǎn):Saga 模式由于一階段已經(jīng)提交本地?cái)?shù)據(jù)庫(kù)事務(wù),且沒有進(jìn)行 “預(yù)留” 動(dòng)作,所以不能保證隔離性。
事務(wù)隔離 縱觀 Seata 提供的所有分支事務(wù)模式,除了 AT 模式和 XA 模式可以運(yùn)行在讀已提交的隔離級(jí)別下,其他模式都是運(yùn)行在讀未提交的級(jí)別下。
在有必要時(shí),應(yīng)用需要通過(guò)業(yè)務(wù)邏輯的巧妙設(shè)定,來(lái)解決分布式事務(wù)隔離級(jí)別帶來(lái)的問(wèn)題 AT 模式通過(guò)全局寫排他鎖,來(lái)保證事務(wù)間的寫隔離,將全局事務(wù)默認(rèn)定義在讀未提交的隔離級(jí)別上,全局事務(wù)讀未提交,并不是說(shuō)本地事務(wù)的 db 數(shù)據(jù)沒有正常提交,而是指全局事務(wù)二階段 commit | rollback 未真正處理完(即未釋放全局鎖),而且這時(shí)候其他事務(wù)會(huì)讀到一階段提交的內(nèi)容。
有些應(yīng)用如果需要達(dá)到全局的讀已提交,AT 也提供了相應(yīng)的機(jī)制來(lái)達(dá)到目的,那就是 select for update +@GlobalLock, 當(dāng)執(zhí)行該命令時(shí) RM 會(huì)去 TC 確認(rèn)該鎖是否由他人占有,這樣如果有一個(gè)分布式事務(wù) T1 正在進(jìn)行中時(shí),另一個(gè)事務(wù) T2 會(huì)因?yàn)榘l(fā)現(xiàn)鎖沖突而阻塞后續(xù)代碼的執(zhí)行,當(dāng)前面的分布式事務(wù) T1 結(jié)束時(shí),釋放了相應(yīng)的資源鎖,T2 才能讀取到相應(yīng)的數(shù)據(jù),這樣就達(dá)到讀已提交的效果
2.6 消息組件
利用 MQ 組件實(shí)現(xiàn)的二階段提交。此方案涉及 3 個(gè)模塊:
上游應(yīng)用,執(zhí)行業(yè)務(wù)并發(fā)送 MQ 消息。
可靠消息服務(wù)和 MQ 消息組件,協(xié)調(diào)上下游消息的傳遞,并確保上下游數(shù)據(jù)的一致性。
下游應(yīng)用,監(jiān)聽 MQ 的消息并執(zhí)行自身業(yè)務(wù)。
上游應(yīng)用將本地業(yè)務(wù)執(zhí)行和消息發(fā)送綁定在同一個(gè)本地事務(wù)中,保證要么本地操作成功并發(fā)送 MQ 消息,要么兩步操作都失敗并回滾。
上游應(yīng)用發(fā)送待確認(rèn)消息到可靠消息系統(tǒng)
可靠消息系統(tǒng)保存待確認(rèn)消息并返回
上游應(yīng)用執(zhí)行本地業(yè)務(wù)
上游應(yīng)用通知可靠消息系統(tǒng)確認(rèn)業(yè)務(wù)已執(zhí)行并發(fā)送消息。
可靠消息系統(tǒng)修改消息狀態(tài)為發(fā)送狀態(tài)并將消息投遞到 MQ 中間件。
下游應(yīng)用監(jiān)聽 MQ 消息組件并獲取消息
下游應(yīng)用根據(jù) MQ 消息體信息處理本地業(yè)務(wù)
下游應(yīng)用向 MQ 組件自動(dòng)發(fā)送 ACK 確認(rèn)消息被消費(fèi)
下游應(yīng)用通知可靠消息系統(tǒng)消息被成功消費(fèi),可靠消息將該消息狀態(tài)更改為已完成。
異常處理 上游異常
可靠消息服務(wù)定時(shí)監(jiān)聽消息的狀態(tài),如果存在狀態(tài)為待確認(rèn)并且超時(shí)的消息,則表示上游應(yīng)用和可靠消息交互中的步驟 4 或者 5 出現(xiàn)異常。
可靠消息查詢超時(shí)的待確認(rèn)狀態(tài)的消息
向上游應(yīng)用查詢業(yè)務(wù)執(zhí)行的情況
業(yè)務(wù)未執(zhí)行,則刪除該消息,保證業(yè)務(wù)和可靠消息服務(wù)的一致性。業(yè)務(wù)已執(zhí)行,則修改消息狀態(tài)為已發(fā)送,并發(fā)送消息到 MQ 組件。
下游異常
可靠消息服務(wù)定時(shí)查詢狀態(tài)為已發(fā)送并超時(shí)的消息
可靠消息將消息重新投遞到 MQ 組件中
下游應(yīng)用監(jiān)聽消息,在滿足冪等性的條件下,重新執(zhí)行業(yè)務(wù)。
下游應(yīng)用通知可靠消息服務(wù)該消息已經(jīng)成功消費(fèi)。
實(shí)際過(guò)程中,還需要引入人工干預(yù)功能。比如引入重發(fā)次數(shù)限制,超過(guò)重發(fā)次數(shù)限制的將消息修改為死亡消息,等待人工處理。
3 總結(jié)
3.1 sql 支持上
AT 其實(shí)就是一個(gè)自實(shí)現(xiàn)的 XA 事務(wù),其實(shí)可以知道,AT 在 sql 支持上遠(yuǎn)不及 XA 模式,AT 需要做 sql 解析背后的實(shí)現(xiàn)只能自己解決,目前只能靠社區(qū)的貢獻(xiàn)者來(lái)提供解決方案,這是一個(gè)長(zhǎng)期的關(guān)鍵性的問(wèn)題,也有很多用戶選擇在 AT 模式上重寫 sql 來(lái)獲取 AT 模式的支持,sql 支持上 XA 是完勝的。
3.2 隔離性
AT 模式是通過(guò)解析 sql 獲取涉及的主鍵 id,生成行鎖。也就是 AT 模式的隔離靠的是全局鎖來(lái)保證的,粒度細(xì)至行級(jí)。鎖信息存儲(chǔ)在 seata server 側(cè)。XA 的隔離級(jí)別是由本地?cái)?shù)據(jù)庫(kù)保證,鎖存儲(chǔ)在各個(gè)本地?cái)?shù)據(jù)庫(kù)中。由于 XA 模式一旦執(zhí)行了 prepare 后,再也無(wú)法重入這個(gè) XA 事務(wù)也無(wú)法跟其他 XA 事務(wù)共享鎖,因?yàn)?XA 協(xié)議僅僅是通過(guò) XID 來(lái) start 一個(gè)事務(wù),本身不存在分支事務(wù)的說(shuō)法。也就是說(shuō)他只管自己
3.3 入侵性
通過(guò)上面的信息可以發(fā)現(xiàn)誰(shuí)更底層,入侵性則更小,所以由數(shù)據(jù)庫(kù)自身支持的 XA 模式來(lái)說(shuō),入侵性無(wú)疑最小,使用成本最低。XA 的 RM 實(shí)際是在數(shù)據(jù)庫(kù),而 AT 則是以中間件層部署在應(yīng)用這一側(cè)的,不依賴數(shù)據(jù)庫(kù)本身的協(xié)議支持,這點(diǎn)對(duì)于微服務(wù)架構(gòu)來(lái)說(shuō)是至關(guān)重要的。應(yīng)用層不需要為本地事務(wù)和分布式事務(wù)多類不同場(chǎng)景來(lái)適配多套不通的驅(qū)動(dòng)
3.4 補(bǔ)償性事務(wù)的問(wèn)題
本質(zhì)上 seata 框架支持了 3 大補(bǔ)償事務(wù)模式,AT, TCC,Saga 都是補(bǔ)償型的。補(bǔ)償型事務(wù)處理機(jī)制是構(gòu)建在事務(wù)資源之上的,事務(wù)資源本身對(duì)分布式事務(wù)是無(wú)感知的,事務(wù)資源對(duì)分布式事務(wù)無(wú)感知存在一個(gè)根本性問(wèn)題,就是無(wú)法做到真正的全局一致性。
比如一條庫(kù)存記錄,處在補(bǔ)償型事務(wù)處理過(guò)程中,由 100 扣減為 50,此時(shí)倉(cāng)庫(kù)管理員連接數(shù)據(jù)庫(kù)查看就會(huì)查詢到 50,之后事務(wù)異常回滾,庫(kù)存就會(huì)被補(bǔ)償回滾為 100,顯然倉(cāng)庫(kù)管理員查詢到的 50 就是臟數(shù)據(jù)。那 XA 的價(jià)值是什么,與補(bǔ)償型事務(wù)不同,XA 協(xié)議要求事務(wù)資源本身提供對(duì)規(guī)范和協(xié)議的支持。
因?yàn)槭聞?wù)資源感知并參與分布式事務(wù)處理過(guò)程,所以事務(wù)資源可以保證從任意視角對(duì)數(shù)據(jù)的訪問(wèn)有效隔離,比如上面 XA 事務(wù)處理過(guò)程中,中間態(tài)的 50 是不會(huì)被查詢到的(當(dāng)然隔離級(jí)別要在讀已提交以上),以此來(lái)滿足全局一致性。
審核編輯:劉清
-
SQL
+關(guān)注
關(guān)注
1文章
783瀏覽量
45087 -
協(xié)調(diào)器
+關(guān)注
關(guān)注
0文章
30瀏覽量
16186 -
CAP
+關(guān)注
關(guān)注
0文章
21瀏覽量
2249
原文標(biāo)題:基于Seata探尋分布式事務(wù)的實(shí)現(xiàn)方案
文章出處:【微信號(hào):OSC開源社區(qū),微信公眾號(hào):OSC開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
潤(rùn)和軟件StackRUNS異構(gòu)分布式推理框架的應(yīng)用案例

潤(rùn)和軟件發(fā)布StackRUNS異構(gòu)分布式推理框架

安科瑞分布式光伏監(jiān)控系統(tǒng):高效、安全、智能的綠色能源解決方案
分布式存儲(chǔ)有哪幾種類型?
鐵塔基站分布式儲(chǔ)能揭秘!

分布式云化數(shù)據(jù)庫(kù)有哪些類型
基于ptp的分布式系統(tǒng)設(shè)計(jì)
HarmonyOS Next 應(yīng)用元服務(wù)開發(fā)-分布式數(shù)據(jù)對(duì)象遷移數(shù)據(jù)權(quán)限與基礎(chǔ)數(shù)據(jù)
分布式光伏監(jiān)控系統(tǒng)在能源領(lǐng)域中的重要性

分布式光纖測(cè)溫是什么?應(yīng)用領(lǐng)域是?

分布式功能安全的創(chuàng)新與突破

基于分布式存儲(chǔ)系統(tǒng)醫(yī)療影像數(shù)據(jù)存儲(chǔ)解決方案

昊衡科技推出分布式光纖傳感教學(xué)解決方案——OFDR技術(shù)首次走進(jìn)課堂,實(shí)現(xiàn)領(lǐng)域創(chuàng)新

評(píng)論