自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何選擇分布式事務(wù)解決方案?

開發(fā) 開發(fā)工具 分布式
分布式事務(wù)中涉及的參與者分布在異步網(wǎng)絡(luò)中,參與者通過網(wǎng)絡(luò)通信來達(dá)到分布式一致性,網(wǎng)絡(luò)通信不可避免出現(xiàn)失敗、超時的情況,因此分布式事務(wù)的實(shí)現(xiàn)比本地事務(wù)面臨更多的困難。本文歸納總結(jié)五種分布式事務(wù)解決方案,并剖析其特點(diǎn)。較長,同學(xué)們可收藏后再看。

 分布式事務(wù)中涉及的參與者分布在異步網(wǎng)絡(luò)中,參與者通過網(wǎng)絡(luò)通信來達(dá)到分布式一致性,網(wǎng)絡(luò)通信不可避免出現(xiàn)失敗、超時的情況,因此分布式事務(wù)的實(shí)現(xiàn)比本地事務(wù)面臨更多的困難。本文歸納總結(jié)五種分布式事務(wù)解決方案,并剖析其特點(diǎn)。較長,同學(xué)們可收藏后再看。

概述

事務(wù)是一組不可分組的操作集合,這些操作要么都成功執(zhí)行,要么都取消執(zhí)行。最典型的需要事務(wù)的場景是銀行賬戶間的轉(zhuǎn)賬:假如 A 賬戶要給 B 賬戶轉(zhuǎn)賬 100 元,那么 A 賬戶要扣減 100 元,B 賬戶要增加 100 元,這兩個賬戶的數(shù)據(jù)變更都成功才可算作轉(zhuǎn)賬成功。更嚴(yán)格來說,可以用 ACID 四個特性表述事務(wù):

  • Atomicity:原子性,事務(wù)中的所有操作要么都成功執(zhí)行,要么都取消執(zhí)行,不能存在部分執(zhí)行,部分不執(zhí)行的狀態(tài)。
  • Consistency:一致性,舉個例子簡單的理解就是,A、B 兩個賬戶各有 100 元,無論兩個賬戶并發(fā)相互轉(zhuǎn)賬多少次,兩個賬戶的資金總額依然是 200 元。
  • Isolation:隔離性,并發(fā)事務(wù)之間的相互影響程度,隔離性也是分級別的:讀未提交、讀已提交、可重復(fù)讀等。
  • Durability:持久性,事務(wù)完成后對數(shù)據(jù)的更改不會丟失。

單體數(shù)據(jù)庫不涉及網(wǎng)絡(luò)交互,所以在多表之間實(shí)現(xiàn)事務(wù)是比較簡單的,這種事務(wù)我們稱之為本地事務(wù)。

但是單體數(shù)據(jù)庫的性能達(dá)到瓶頸的時候,就需要分庫(分物理實(shí)例),就會出現(xiàn)跨庫(數(shù)據(jù)庫實(shí)例)的事務(wù)需求;隨著企業(yè)應(yīng)用的規(guī)模越來越大,企業(yè)會進(jìn)一步進(jìn)行服務(wù)化改造,以滿足業(yè)務(wù)增長的需求;當(dāng)前微服務(wù)架構(gòu)越來越流行,跨服務(wù)的事務(wù)場景也會越來越多。

這些都是分布式事務(wù)的需求。分布式事務(wù)是指是指事務(wù)的發(fā)起者、參與者、數(shù)據(jù)資源服務(wù)器以及事務(wù)管理器分別位于分布式系統(tǒng)的不同節(jié)點(diǎn)之上。

概括起來,分布式事務(wù)有三種場景:

  • 跨數(shù)據(jù)庫分布式事務(wù)
  • 跨服務(wù)分布式事務(wù)
  • 混合式分布式事務(wù)

??

??

 

分布式事務(wù)中涉及的參與者分布在異步網(wǎng)絡(luò)中,參與者通過網(wǎng)絡(luò)通信來達(dá)到分布式一致性,網(wǎng)絡(luò)通信不可避免出現(xiàn)失敗、超時的情況,因此分布式事務(wù)的實(shí)現(xiàn)比本地事務(wù)面臨更多的困難。下面介紹幾種常見的分布式事務(wù)解決方案。

分布式事務(wù)模式

XA Specification

最早的分布式事務(wù)產(chǎn)品可能是 AT&T 在 20 世紀(jì) 80 年代推出的 Tuxedo (Transactions for Unix, Extended for Distributed Operations),Tuxedo 最早是為了電信領(lǐng)域的 OLTP 系統(tǒng)研發(fā)的分布式事務(wù)中間件,后來標(biāo)準(zhǔn)化組織 X/Open 吸收采納了 Tuxedo 的設(shè)計(jì)思想和一些接口,推出了分布式事務(wù)規(guī)范:XA Specification。

XA 規(guī)范中定義了分布式事務(wù)處理模型,這個模型中包含四個核心角色:

  • RM (Resource Managers):資源管理器,提供數(shù)據(jù)資源的操作、管理接口,保證數(shù)據(jù)的一致性和完整性。最有代表性的就是數(shù)據(jù)庫管理系統(tǒng),當(dāng)然有的文件系統(tǒng)、MQ 系統(tǒng)也可以看作 RM。
  • TM (Transaction Managers):事務(wù)管理器,是一個協(xié)調(diào)者的角色,協(xié)調(diào)跨庫事務(wù)關(guān)聯(lián)的所有 RM 的行為。
  • AP (Application Program):應(yīng)用程序,按照業(yè)務(wù)規(guī)則調(diào)用 RM 接口來完成對業(yè)務(wù)模型數(shù)據(jù)的變更,當(dāng)數(shù)據(jù)的變更涉及多個 RM 且要保證事務(wù)時,AP 就會通過 TM 來定義事務(wù)的邊界,TM 負(fù)責(zé)協(xié)調(diào)參與事務(wù)的各個 RM 一同完成一個全局事務(wù)。
  • CRMs (Communication Resource Managers):主要用來進(jìn)行跨服務(wù)的事務(wù)的傳播。

下圖是 XA 規(guī)范中定義的事務(wù)模型圖,其中:發(fā)起分布式事務(wù)的 TM 實(shí)例稱之為 root 節(jié)點(diǎn),其他的 TM 實(shí)例可以統(tǒng)稱為事務(wù)的參與者。事務(wù)發(fā)起者負(fù)責(zé)開啟整個全局事務(wù),事務(wù)參與者各自負(fù)責(zé)執(zhí)行自己的事務(wù)分支。如果TM實(shí)例發(fā)起了對其他 TM 實(shí)例的服務(wù)調(diào)用,那么發(fā)起者就被成為 Superior,被調(diào)用這就被稱之為 Subordinate 節(jié)點(diǎn)。

??

??

 

圖源:《Distributed Transaction Processing:Reference Model, Version 3》 Page 32,Figure 3-2

XA 規(guī)范中分布式事務(wù)是構(gòu)建在 RM 本地事務(wù)(此時本地事務(wù)被看作分支事務(wù))的基礎(chǔ)上的,TM 負(fù)責(zé)協(xié)調(diào)這些分支事務(wù)要么都成功提交、要么都回滾。XA 規(guī)范把分布式事務(wù)處理過程劃分為兩個階段,所以又叫兩階段提交協(xié)議(two phrase commit):

1)預(yù)備階段

TM 記錄事務(wù)開始日志,并詢問各個 RM 是否可以執(zhí)行提交準(zhǔn)備操作。

RM 收到指令后,評估自己的狀態(tài),嘗試執(zhí)行本地事務(wù)的預(yù)備操作:預(yù)留資源,為資源加鎖、執(zhí)行操作等,但是并不提交事務(wù),并等待 TM 的后續(xù)指令。如果嘗試失敗則告知 TM 本階段執(zhí)行失敗并且回滾自己的操作,然后不再參與本次事務(wù)(以 MySQL 為例,這個階段會完成資源的加鎖,redo log 和 undo log 的寫入)。

TM 收集 RM 的響應(yīng),記錄事務(wù)準(zhǔn)備完成日志。

2)提交/回滾階段

這個階段根據(jù)上個階段的協(xié)調(diào)結(jié)果發(fā)起事務(wù)的提交或者回滾操作。

如果所有 RM 在上一個步驟都返回執(zhí)行成功,那么:

  • TM 記錄事務(wù) commit 日志,并向所有 RM 發(fā)起事務(wù)提交指令。
  • RM 收到指令后,提交事務(wù),釋放資源,并向 TM 響應(yīng)“提交完成”。
  • 如果 TM 收到所有 RM 的響應(yīng),則記錄事務(wù)結(jié)束日志。

如果有 RM 在上一個步驟中返回執(zhí)行失敗或者超時沒有應(yīng)答,則 TM 按照執(zhí)行失敗處理,那么:

  • 記錄事務(wù) abort 日志,向所有 RM 發(fā)送事務(wù)回滾指令。
  • RM 收到指令后,回滾事務(wù),釋放資源,并向 TM 響應(yīng)回滾完成。
  • 如果 TM 收到所有 RM 的響應(yīng),則記錄事務(wù)結(jié)束日志。

??

??

 

針對部分場景,XA 規(guī)范還定義了如下優(yōu)化措施:

  • 如果 TM 發(fā)現(xiàn)整個事務(wù)只涉及到一個 RM,那么就會將整個過程退化為一階段提交。
  • 如果 RM 收到的 AP 的數(shù)據(jù)操作是只讀操作,那么它可以在階段 1 就將事務(wù)完成并告知 TM 其不再參與階段 2 的過程。會有臟讀的風(fēng)險。
  • 如果 RM 在階段1完成后,長時間等不到階段 2 的指令,那么其可以自動提交或者回滾本地事務(wù)。這叫做 Heuristic Completion,注意這種場景有可能會破壞事務(wù)的一致性,產(chǎn)生異常。

XA 規(guī)范中詳細(xì)定義了各個核心組件之間的交互接口,以 TM 和 RM 的交互接口為例,如下圖,一次完整的全局事務(wù),TM 和 RM 之間的交互還是比較頻繁的:

??

??

 

事務(wù)的執(zhí)行過程中,宕機(jī)和網(wǎng)絡(luò)超時都有可能發(fā)生,針對這些異常場景,不同 XA 規(guī)范的實(shí)現(xiàn),對異常處理做法可能不同,可參考如下:

  • TM 在階段 1 中詢問 RM 前宕機(jī),恢復(fù)后無需做任何操作。
  • TM 在階段 1 中詢問 RM 后宕機(jī),可能只有部分 RM 收到了階段 1 的請求,因此此時需要向 RM 發(fā)起回滾請求。
  • TM 在階段 1 中詢問 RM 完畢,但是在就準(zhǔn)備完成日志時宕機(jī),因不清楚宕機(jī)前的事務(wù)協(xié)商的結(jié)果,因此恢復(fù)后需要向 RM 發(fā)起回滾請求。
  • TM 在階段 1 中記錄完畢事務(wù)準(zhǔn)備完成日志后宕機(jī),恢復(fù)后可以根據(jù)日志發(fā)起提交或者回滾的指令。
  • TM 在階段 2 中記錄 commit/abort 日志前宕機(jī),恢復(fù)后可以根據(jù)日志發(fā)起提交或者回滾指令。
  • TM 在階段 2 中記錄事務(wù)結(jié)束日志前宕機(jī),恢復(fù)后可以根據(jù)日志發(fā)起提交或者回滾指令。
  • TM 在階段 2 中記錄事務(wù)結(jié)束日志后宕機(jī),恢復(fù)后無需做任何操作。
  • 階段 1 中,RM 有超時情況時,TM 按失敗處理,給所有 RM 發(fā)送回滾指令。
  • 階段 2 中,RM 有超時情況是,TM 需要對超時的 RM 持續(xù)重復(fù)發(fā)送指令。

特點(diǎn)剖析

XA 兩階段提交協(xié)議設(shè)計(jì)上是要像本地事務(wù)一樣實(shí)現(xiàn)事務(wù)的 ACID 四個特性:

  • 原子性:在 prepare 和 commit 階段保證事務(wù)是原子性的。
  • 一致性:XA 協(xié)議實(shí)現(xiàn)的是強(qiáng)一致性。
  • 隔離性:XA 事務(wù)在完成之前一直持有資源的鎖,所以可以做到寫隔離。
  • 持久性:基于本地事務(wù)實(shí)現(xiàn),所以這一點(diǎn)沒有問題。

XA 是出現(xiàn)最早的分布式事務(wù)規(guī)范,主流數(shù)據(jù)庫 Oracle、MySQL、SQLServer 等都支持 XA 規(guī)范,J2EE 中的 JTA 規(guī)范也是參照 XA 規(guī)范編寫的,與 XA 規(guī)范兼容。

XA 是在資源管理層面實(shí)現(xiàn)的分布式事務(wù)模型,對業(yè)務(wù)的入侵度較低。

XA 兩階段提交協(xié)議可以覆蓋分布式事務(wù)的三種場景,但是全局事務(wù)的執(zhí)行過程中,RM 一直持有資源的鎖,如果參與的 RM 過多,尤其是跨服務(wù)的場景下,網(wǎng)絡(luò)通信的次數(shù)和時間會急劇變多,所以阻塞的時間更長,系統(tǒng)的吞吐能力變得很差,事務(wù)死鎖出現(xiàn)的概率也會變大,所以并不適合微服務(wù)架構(gòu)場景中的跨服務(wù)的分布式事務(wù)模式。

每一個 TM 域來說,由于 TM 是單點(diǎn),存在單點(diǎn)故障風(fēng)險,如果 TM 在階段1之后掛掉,會導(dǎo)致參與的 RM 長時間收不到階段 2 的請求而長期持有資源的鎖,影響業(yè)務(wù)的吞吐能力。同時一次完整的全局事務(wù),TM 和 RM 之間的交互多達(dá) 8 次,太繁瑣,非常影響系統(tǒng)的處理性能。

XA 兩階段協(xié)議可能會造成腦裂的異常,假如 TM 在階段 2 通知 RM 提交事務(wù)時,如果指令發(fā)出后就宕機(jī)了,而只有部分 RM 收到了提交請求,那么當(dāng) TM 恢復(fù)的時候,就無法協(xié)調(diào)本次事務(wù)所有的 RM 本地事務(wù)的一致性了。

XA 要處理的異常場景非常多,對框架的實(shí)現(xiàn)有一定的挑戰(zhàn),開源的實(shí)現(xiàn),可以參考:Atomikos,Bitronix。

針對 XA 兩階段提交中的問題,有人提出了三階段提交的改進(jìn)方案,三階段提交方案主要解決了單點(diǎn)故障問題,并在 RM 側(cè)也引入了超時機(jī)制,以避免資源的長時間鎖定。但是三階段提交方案依然無法避免腦裂的異常情況出現(xiàn),實(shí)際應(yīng)用案例很少,感興趣的同學(xué)可以自行找相關(guān)資料了解。

TCC

TCC (Try、Commit、Cancel) 是一種補(bǔ)償型事務(wù),該模型要求應(yīng)用的每個服務(wù)提供 try、confirm、cancel 三個接口,它的核心思想是通過對資源的預(yù)留(提供中間態(tài)),盡早釋放對資源的加鎖,如果事務(wù)可以提交,則完成對預(yù)留資源的確認(rèn),如果事務(wù)要回滾,則釋放預(yù)留的資源。

TCC 也是一種兩階段提交協(xié)議,可以看作 2PC/XA 的一種變種,但是不會長時間持有資源鎖。

TCC 模型將事務(wù)的提交劃分為兩個階段:

1)階段 1

完成業(yè)務(wù)檢查(一致性)、預(yù)留業(yè)務(wù)資源(準(zhǔn)隔離性),即 TCC 中的 try。

2)階段 2

如果 try 階段所有業(yè)務(wù)資源都預(yù)留成功,則執(zhí)行 confirm 操作,否則執(zhí)行 cancel 操作:

  • confirm:不做任何業(yè)務(wù)檢查,僅僅使用預(yù)留的資源執(zhí)行業(yè)務(wù)操作,如果失敗會一直重試。
  • cancel:取消執(zhí)行業(yè)務(wù)操作,釋放預(yù)留的資源,如果失敗會一直重試。

??

??

 

TCC 模式中,事務(wù)的發(fā)起者和參與者都需要記錄事務(wù)日志,事務(wù)的發(fā)起者需要記錄全局事務(wù)和各個分支事務(wù)的狀態(tài)和信息;事務(wù)的參與者需要記錄分支事務(wù)的狀態(tài)。

TCC 事務(wù)在執(zhí)行過程中的任意環(huán)節(jié),均可能發(fā)生宕機(jī)、重啟、網(wǎng)絡(luò)中斷等異常情況,此時事務(wù)處于非原子狀態(tài)和非最終一致狀態(tài),此時就需要根據(jù)主事務(wù)記錄和分支事務(wù)記錄的日志,去完成剩余分支事務(wù)的提交或者回滾,使整個分布式事務(wù)內(nèi)所有參展達(dá)到最終一致的狀態(tài),實(shí)現(xiàn)事務(wù)的原子性。

舉例

我們以一個簡單的電商系統(tǒng)為例,小明在淘寶上花 100 元買了一本書,獲贈 10 個積分,產(chǎn)品上有如下幾個操作:

訂單系統(tǒng)創(chuàng)建商品訂單

支付系統(tǒng)接受小明的支付

庫存系統(tǒng)扣減產(chǎn)品庫存

會員系統(tǒng)給小明賬戶增加會員積分

這幾個動作需要作為一個事務(wù)執(zhí)行,要同時成功或者同時撤銷。

如果采用 TCC 事務(wù)模式,那么各個系統(tǒng)需要改造為如下狀態(tài):

1)訂單系統(tǒng)

  • try:創(chuàng)建一個訂單,狀態(tài)顯示為“待支付”
  • confirm:更新訂單的狀態(tài)為“已完成”
  • cancel:更新訂單的狀態(tài)為“已取消”

2)支付系統(tǒng)

  • try:假設(shè)小明賬戶中有 1000 元,凍結(jié)小明賬戶中的 100 元,此時小明看到的余額依然是 1000 元。
  • confirm:將賬戶余額變?yōu)?900 元,并清除凍結(jié)記錄。
  • concel:清除凍結(jié)記錄。

3)庫存系統(tǒng)

  • try:假設(shè)庫存中還生 10 本書,凍結(jié)其中的一本書,現(xiàn)實(shí)庫存依然有 10 本書。
  • confirm:將剩余庫存更新為 9 本書,并清除凍結(jié)記錄。
  • cancel:清除凍結(jié)記錄。

4)會員系統(tǒng)

  • try:假設(shè)小明原因積分 3000 分,給小明賬戶預(yù)增加 10 積分,賬戶顯示的積分依然是 3000 分。
  • confirm:將賬戶積分更新為 3010,并清除預(yù)增加記錄。
  • cancel:清除預(yù)增加記錄。

特點(diǎn)剖析

TCC 事務(wù)具備事務(wù)的四個特性:

  • 原子性:事務(wù)發(fā)起方協(xié)調(diào)各個分支事務(wù)全部提交或者全部回滾。
  • 一致性:TCC 事務(wù)提供最終一致性。
  • 隔離型:通過 try 預(yù)分配資源的方式來實(shí)現(xiàn)數(shù)據(jù)的隔離。
  • 持久性:交由各個分支事務(wù)來實(shí)現(xiàn)。

TCC 事務(wù)模型對業(yè)務(wù)方侵入較大,需要業(yè)務(wù)方把功能的實(shí)現(xiàn)上由一個接口拆分為三個,開發(fā)成本較高。

同時 TCC 事務(wù)為了解決異步網(wǎng)絡(luò)中的通信失敗或超時帶來的異常情況,要求業(yè)務(wù)方在設(shè)計(jì)實(shí)現(xiàn)上要遵循三個策略:

  • 允許空回滾:原因是異常發(fā)生在階段 1 時,部分參與方?jīng)]有收到 try 請求從而觸發(fā)整個事務(wù)的 cancel 操作,try 失敗或者沒有執(zhí)行 try 操作的參與方收到 cancel 請求時,要進(jìn)行空回滾操作。
  • 保持冪等性:原因是異常發(fā)生在階段 2 時,比如網(wǎng)絡(luò)超時,則會重復(fù)調(diào)用參與方的 confirm/cancel 方法,因此需要這兩個方法實(shí)現(xiàn)上保證冪等性。
  • 防止資源懸掛:原因網(wǎng)絡(luò)異常導(dǎo)致兩個階段無法保證嚴(yán)格的順序執(zhí)行,出現(xiàn)參與方側(cè) try 請求比 cancel 請求更晚到達(dá)的情況,cancel 會執(zhí)行空回滾而確保事務(wù)的正確性,但是此時 try 方法也不可以再被執(zhí)行。

TCC 事務(wù)將分布式事務(wù)從資源層提到業(yè)務(wù)層來實(shí)現(xiàn),可以讓業(yè)務(wù)靈活選擇資源的鎖定粒度,并且全局事務(wù)執(zhí)行過程中不會一直持有鎖,所以系統(tǒng)的吞吐量比 2PC/XA 模式要高很多。

支持 TCC 事務(wù)的開源框架有:ByteTCC、Himly、TCC-transaction。

Saga

Saga 并不是一個新概念,其相關(guān)論文在 1987 年就發(fā)布了,和 XA 兩階段提交規(guī)范出現(xiàn)的時間差不多。

Saga 和 TCC 一樣,也是一種補(bǔ)償事務(wù),但是它沒有 try 階段,而是把分布式事務(wù)看作一組本地事務(wù)構(gòu)成的事務(wù)鏈。

事務(wù)鏈中的每一個正向事務(wù)操作,都對應(yīng)一個可逆的事務(wù)操作。Saga 事務(wù)協(xié)調(diào)器負(fù)責(zé)按照順序執(zhí)行事務(wù)鏈中的分支事務(wù),分支事務(wù)執(zhí)行完畢,即釋放資源。如果某個分支事務(wù)失敗了,則按照反方向執(zhí)行事務(wù)補(bǔ)償操作。

假如一個 Saga 的分布式事務(wù)鏈有 n 個分支事務(wù)構(gòu)成,[T1,T2,...,Tn],那么該分布式事務(wù)的執(zhí)行情況有三種:

  • T1,T2,...,Tn:n 個事務(wù)全部執(zhí)行成功了。
  • T1,T2,...,Ti,Ci,...,C2,C1:執(zhí)行到第 i (i<=n) 個事務(wù)的時候失敗了,則按照 i->1 的順序依次調(diào)用補(bǔ)償操作。如果補(bǔ)償失敗了,就一直重試。補(bǔ)償操作可以優(yōu)化為并行執(zhí)行。
  • T1,T2,...,Ti (失敗),Ti (重試),Ti (重試),...,Tn:適用于事務(wù)必須成功的場景,如果發(fā)生失敗了就一直重試,不會執(zhí)行補(bǔ)償操作。

??

??

 

舉例

假如國慶節(jié)小明要出去玩,從北京出發(fā),先去倫敦,在倫敦游玩三天,再去巴黎,在巴黎游玩三天,然后再返回北京。整個行程中涉及不同航空公司的機(jī)票預(yù)訂以及倫敦和巴黎當(dāng)?shù)氐木频觐A(yù)訂,小明的計(jì)劃是如果任何一張機(jī)票或酒店預(yù)訂不上,就取消本次出行計(jì)劃。假如綜合旅游出行服務(wù)平臺提供這種一鍵下單的功能,那么這就是一個長事務(wù),用 Saga 模式編排服務(wù)的話,就如下圖所示:任何一個環(huán)節(jié)失敗的話,就通過補(bǔ)償操作取消前面的行程預(yù)訂。

??

??

 

特點(diǎn)剖析

Saga 事務(wù)是可以保障事務(wù)的三個特性:

  • 原子性:Saga 協(xié)調(diào)器可以協(xié)調(diào)事務(wù)鏈中的本地事務(wù)要么全部提交,要么全部回滾。
  • 一致性:Saga 事務(wù)可以實(shí)現(xiàn)最終一致性。
  • 持久性:基于本地事務(wù),所以這個特性可以很好實(shí)現(xiàn)。

但是 Saga 不保證事務(wù)隔離性的,本地事務(wù)提交后變更就對其他事務(wù)可見了。其他事務(wù)如果更改了已經(jīng)提交成功的數(shù)據(jù),可能會導(dǎo)致補(bǔ)償操作失敗。比如扣款失敗,但是錢已經(jīng)花掉了,業(yè)務(wù)設(shè)計(jì)上需要考慮這種場景并從業(yè)務(wù)設(shè)計(jì)上規(guī)避這種問題。

Saga 事務(wù)和 TCC 事務(wù)一樣,對業(yè)務(wù)實(shí)現(xiàn)要求高,要求業(yè)務(wù)設(shè)計(jì)實(shí)現(xiàn)上遵循三個策略:

  • 允許空補(bǔ)償:網(wǎng)絡(luò)異常導(dǎo)致事務(wù)的參與方只收到了補(bǔ)償操作指令,因?yàn)闆]有執(zhí)行過正常操作,因此要進(jìn)行空補(bǔ)償。
  • 保持冪等性:事務(wù)的正向操作和補(bǔ)償操作都可能被重復(fù)觸發(fā),因此要保證操作的冪等性。
  • 防止資源懸掛:網(wǎng)絡(luò)異常導(dǎo)致事務(wù)的正向操作指令晚于補(bǔ)償操作指令到達(dá),則要丟棄本次正常操作,否則會出現(xiàn)資源懸掛問題。

雖然 Saga 和 TCC 都是補(bǔ)償事務(wù),但是由于提交階段不同,所以兩者也是有不同的:

  • Saga 是不完美補(bǔ)償,補(bǔ)償操作會留下之前原始事務(wù)操作的痕跡,需要考慮對業(yè)務(wù)上的影響。
  • TCC 是完美補(bǔ)償,補(bǔ)償操作會徹底清理之前的原始事務(wù)操作,用戶是感知不到事務(wù)取消之前的狀態(tài)信息的。
  • TCC 的事務(wù)可以更好的支持異步化,但是 Saga 模式一般在補(bǔ)償階段比較適合異步化。

Saga 模式非常適合于業(yè)務(wù)流程長的長事務(wù)的場景,實(shí)現(xiàn)上對業(yè)務(wù)侵入低,所以非常適合微服務(wù)架構(gòu)的場景。同時 Saga 采用的是一階段提交模式,不會對資源長時間加鎖,不存在“木桶效應(yīng)”,所以采用這種模式架構(gòu)的系統(tǒng)性能高、吞吐高。

阿里巴巴的 Seata 開源項(xiàng)目和華為的 ServiceComb 開源項(xiàng)目都支持 Saga 模式。

基于消息的分布式事務(wù)

基于消息的分布式事務(wù)模式核心思想是通過消息系統(tǒng)來通知其他事務(wù)參與方自己事務(wù)的執(zhí)行狀態(tài)。

消息系統(tǒng)的引入更有效的將事務(wù)參與方解耦,各個參與方可以異步執(zhí)行。

該種模式的難點(diǎn)在于解決本地事務(wù)執(zhí)行和消息發(fā)送的一致性:兩者要同時執(zhí)行成功或者同時取消執(zhí)行。

實(shí)現(xiàn)上主要有兩種方式:

  • 基于事務(wù)消息的方案
  • 基于本地消息的方案

基于事務(wù)消息的分布式事務(wù)

普通消息是無法解決本地事務(wù)執(zhí)行和消息發(fā)送的一致性問題的。因?yàn)橄l(fā)送是一個網(wǎng)絡(luò)通信的過程,發(fā)送消息的過程就有可能出現(xiàn)發(fā)送失敗、或者超時的情況。超時有可能發(fā)送成功了,有可能發(fā)送失敗了,消息的發(fā)送方是無法確定的,所以此時消息發(fā)送方無論是提交事務(wù)還是回滾事務(wù),都有可能不一致性出現(xiàn)。

解決這個問題,需要引入事務(wù)消息,事務(wù)消息和普通消息的區(qū)別在于事務(wù)消息發(fā)送成功后,處于 prepared 狀態(tài),不能被訂閱者消費(fèi),等到事務(wù)消息的狀態(tài)更改為可消費(fèi)狀態(tài)后,下游訂閱者才可以監(jiān)聽到次消息。

本地事務(wù)和事務(wù)消息的發(fā)送的處理流程如下:

  • 事務(wù)發(fā)起者預(yù)先發(fā)送一個事務(wù)消息。
  • MQ 系統(tǒng)收到事務(wù)消息后,將消息持久化,消息的狀態(tài)是“待發(fā)送”,并給發(fā)送者一個 ACK 消息。
  • 事務(wù)發(fā)起者如果沒有收到 ACK 消息,則取消本地事務(wù)的執(zhí)行;如果收到了 ACK 消息,則執(zhí)行本地事務(wù),并給 MQ 系統(tǒng)再發(fā)送一個消息,通知本地事務(wù)的執(zhí)行情況。
  • MQ 系統(tǒng)收到消息通知后,根據(jù)本地事務(wù)的執(zhí)行情況更改事務(wù)消息的狀態(tài),如果成功執(zhí)行,則將消息更改為“可消費(fèi)”并擇機(jī)下發(fā)給訂閱者;如果事務(wù)執(zhí)行失敗,則刪除該事務(wù)消息。
  • 本地事務(wù)執(zhí)行完畢后,發(fā)給 MQ 的通知消息有可能丟失了。所以支持事務(wù)消息的 MQ 系統(tǒng)有一個定時掃描邏輯,掃描出狀態(tài)仍然是“待發(fā)送”狀態(tài)的消息,并向消息的發(fā)送方發(fā)起詢問,詢問這條事務(wù)消息的最終狀態(tài)如何并根據(jù)結(jié)果更新事務(wù)消息的狀態(tài)。因此事務(wù)的發(fā)起方需要給 MQ 系統(tǒng)提供一個事務(wù)消息狀態(tài)查詢接口。
  • 如果事務(wù)消息的狀態(tài)是“可發(fā)送”,則 MQ 系統(tǒng)向下游參與者推送消息,推送失敗會不停重試。
  • 下游參與者收到消息后,執(zhí)行本地事務(wù),本地事務(wù)如果執(zhí)行成功,則給 MQ 系統(tǒng)發(fā)送 ACK 消息;如果執(zhí)行失敗,則不發(fā)送 ACK 消息,MQ 系統(tǒng)會持續(xù)推送給消息。

??

??

 

基于本地消息的分布式事務(wù)

基于事務(wù)消息的模式對 MQ 系統(tǒng)要求較高,并不是所有 MQ 系統(tǒng)都支持事務(wù)消息的,RocketMQ 是目前為數(shù)不多的支持事務(wù)小的 MQ 系統(tǒng)。如果所依賴的 MQ 系統(tǒng)不支持事務(wù)消息,那么可以采用本地消息的分布式模式。

該種模式的核心思想是事務(wù)的發(fā)起方維護(hù)一個本地消息表,業(yè)務(wù)執(zhí)行和本地消息表的執(zhí)行處在同一個本地事務(wù)中。業(yè)務(wù)執(zhí)行成功,則同時記錄一條“待發(fā)送”狀態(tài)的消息到本地消息表中。系統(tǒng)中啟動一個定時任務(wù)定時掃描本地消息表中狀態(tài)為“待發(fā)送”的記錄,并將其發(fā)送到 MQ 系統(tǒng)中,如果發(fā)送失敗或者超時,則一直發(fā)送,知道發(fā)送成功后,從本地消息表中刪除該記錄。后續(xù)的消費(fèi)訂閱流程則與基于事務(wù)消息的模式雷同。

??

??

 

特點(diǎn)剖析

基于消息的分布式事務(wù)模式對 ACID 特性的支持如下:

  • 原子性:最終可以實(shí)現(xiàn)分支事務(wù)都執(zhí)行或者都不執(zhí)行。
  • 一致性:提供最終一致性。
  • 隔離性:不保障隔離性。
  • 持久性:由本地事務(wù)來保證。

基于消息的分布式事務(wù)可以將分布式系統(tǒng)之間更有效的解耦,各個事務(wù)參與方之間的調(diào)用不再是同步調(diào)用。

對 MQ 系統(tǒng)的要求較高,對業(yè)務(wù)實(shí)現(xiàn)也有一定的侵入性,要么提供事務(wù)消息狀態(tài)查詢接口,要么需要維護(hù)本地消息表。并且原則上只接受下游分支事務(wù)的成功,不接受事務(wù)的回滾,如果失敗就要一直重試,適用于對最終一致性敏感度較低的業(yè)務(wù)場景,例如跨企業(yè)的系統(tǒng)間的調(diào)用,適用的場景有限。

最大努力通知型分布式事務(wù)

最大努力通知型的分布式事務(wù)解決方案,也是基于 MQ 系統(tǒng)的一種解決方案,但是不要求 MQ 消息可靠。

舉例

假設(shè)小明通過聯(lián)通的網(wǎng)上營業(yè)廳為手機(jī)充話費(fèi),充值方式選擇支付寶支付。整個操作的流程如下:

  • 小明選擇充值金額“50 元”,支付方式“支付寶”。
  • 聯(lián)通網(wǎng)上營業(yè)廳創(chuàng)建一個充值訂單,狀態(tài)為“支付中”,并跳轉(zhuǎn)到支付寶的支付頁面(此時進(jìn)入了支付寶的系統(tǒng)中)。
  • 支付寶驗(yàn)明確認(rèn)小明的支付后,從小明的賬戶中扣除 50 元,并向聯(lián)通的賬戶中增加 50 元。執(zhí)行完畢后向 MQ 系統(tǒng)發(fā)送一條消息,消息的內(nèi)容標(biāo)識支付是否成功,消息發(fā)送允許失敗。
  • 如果消息發(fā)送成功,那么支付寶的通知服務(wù)會訂閱到該消息,并調(diào)用聯(lián)通的接口通知本次支付的結(jié)果。如果此時聯(lián)通的服務(wù)掛掉了,導(dǎo)致通知失敗了,則會按照 5min、10min、30min、1h、...、24h 等遞增的時間間隔,間隔性重復(fù)調(diào)用聯(lián)通的接口,直到調(diào)用成功或者達(dá)到預(yù)訂的時間窗口上限后,則不再通知。這就是盡最大努力通知的含義。
  • 如果聯(lián)通服務(wù)恢復(fù)正常,收到了支付寶的通知,如果支付成功,則給賬戶充值;如果支付失敗,則取消充值。執(zhí)行完畢后給支付寶通知服務(wù)確認(rèn)響應(yīng),確認(rèn)響應(yīng)允許失敗,支付寶系統(tǒng)會繼續(xù)重試。所以聯(lián)通的充值接口需要保持冪等性。
  • 如果聯(lián)通服務(wù)故障時間很久,恢復(fù)正常后,已超出支付寶通知服務(wù)的時間窗口,則聯(lián)通掃描“支付中”的訂單,主動向支付寶發(fā)起請求,核驗(yàn)訂單的支付結(jié)果。

特點(diǎn)剖析

最大努力通知型方案本質(zhì)是通過引入定期校驗(yàn)機(jī)制來對最終一致性做兜底,對業(yè)務(wù)侵入性較低、對 MQ 系統(tǒng)要求較低,實(shí)現(xiàn)比較簡單,適合于對最終一致性敏感度比較低、業(yè)務(wù)鏈路較短的場景,比如跨平臺、跨企業(yè)的系統(tǒng)間的業(yè)務(wù)交互。

分布式事務(wù)中間件

阿里巴巴有兩個分布式事務(wù)中間件可選擇:

  • 螞蟻金服團(tuán)隊(duì)開發(fā)的 XTS,金融云產(chǎn)品名稱為 DTX。
  • 阿里巴巴中間件團(tuán)隊(duì)開發(fā)的 TXC。

XTS 和 TXC 的功能差不多,都支持 TCC 事務(wù)模式,也都提供了對業(yè)務(wù)入侵度較低的分布式事務(wù)方案,目前這兩個團(tuán)隊(duì)?wèi)?yīng)該是在共建開源版的分布式事務(wù)中間件 Seata。此處我們介紹一下 Seata。

Seata

簡單說一下 Seata (Simple Extensible Autonomous Transaction Architecture) 的歷史:

  • 2014 年阿里巴巴就已經(jīng)推出了分布式事務(wù)中間件產(chǎn)品 TXC (Taobao Transaction Constructor)。
  • 2016 年,TXC 進(jìn)行了云產(chǎn)品化改造,提供了阿里云的云版本,名字叫做 GTS (Global Transaction Service) 。
  • 2019 年,GTS 宣布開源,開源項(xiàng)目的名字叫做 Seata。

Seata 支持 TCC 模式、Saga 模式。但是 Seata 對 TCC 模式的支持提供了一種對業(yè)務(wù)入侵度為0的解決方案,這種方案叫做 AT (Automatic Transaction) 模式。下面我們重點(diǎn)說一下 AT 模式的運(yùn)行機(jī)制:

  • 全局事務(wù)依然是基于各個分支事務(wù)來完成。Seata Server 協(xié)調(diào)各個分支事務(wù)要么一起提交,要么一起回滾。
  • 各個分支事務(wù)在運(yùn)行時,Seata Client 通過對 SQL 執(zhí)行的代理和攔截,通過解析 SQL 定位到行記錄,記錄下 SQL 執(zhí)行前后的行數(shù)據(jù)快照,beforeImage 和 afterImage 共同構(gòu)成了回滾日志,回滾日志記錄在獨(dú)立的表中?;貪L日志的寫入和業(yè)務(wù)數(shù)據(jù)的更改在在同一個本地事務(wù)中提交。
  • 分支事務(wù)完成后,立即釋放對本地資源的鎖,然后給 Seata 協(xié)調(diào)器上報事務(wù)執(zhí)行的結(jié)果。
  • Seata 協(xié)調(diào)器匯總各個分支事務(wù)的完成情況,生成事務(wù)提交或者回滾的決議,將決議下發(fā)給 Seata Client。
  • 如果決議是提交事務(wù),則 Seata Client 異步清理回滾日志;如果決議是回滾事務(wù),則 Seata Client 根據(jù)回滾日志進(jìn)行補(bǔ)償操作,補(bǔ)償前會對比當(dāng)前數(shù)據(jù)快照和 afterImage 是否一致,如果不一致則回滾失敗,需要人工介入。

??

??

 

AT 模式通過自動生成回滾日志的方式,使得業(yè)務(wù)方接入成本低,對業(yè)務(wù)入侵度很低,但是應(yīng)用 AT 模式也有一些限制:

  • AT 模式只支持基于 ACID 事務(wù)的關(guān)系數(shù)據(jù)庫。
  • AT 模式是通過對 SQL 解析來完成的,對 SQL 語法的支持有限,使用復(fù)雜 SQL 時需要考慮兼容性。
  • 目前不支持復(fù)合主鍵,業(yè)務(wù)表在設(shè)計(jì)時注意添加自增主鍵。
  • 全局事務(wù)默認(rèn)的隔離級別是讀未提交,但是通過 SELECT...FOR UPDATE 等語句,可以實(shí)現(xiàn)讀已提交的隔離級別。通過全局排它寫鎖,可以做到的隔離級別介于讀未提交和讀已提交之間。

總結(jié)

單體數(shù)據(jù)庫事務(wù)很容易滿足事務(wù)的 ACID 四個特性,提供強(qiáng)一致性保證,但是分布式事務(wù)要完全遵循 ACID 特性會比較困難。為了追求分布式系統(tǒng)的高可用和高吞吐,分布式事務(wù)的解決方案一般提供的是最終一致性。

我們把提供強(qiáng)一致性的事務(wù)稱之為剛性事務(wù),把提供最終一致性的事務(wù)稱之為柔性事務(wù)。剛性事務(wù)可以完全滿足 ACID 四個特性,柔性事務(wù)對事務(wù)的 ACID 特性的支持情況如下:

  • 原子性:完全支持。
  • 一致性:只提供最終一致性支持。
  • 隔離性:不完全保證,通常為了系統(tǒng)的吞吐和性能,會一定程度上放棄對隔離性的要求。
  • 持久性:完全支持。

柔性事務(wù)一般遵循的是分布式領(lǐng)域中的 BASE 理論:

  • BA:Basic Availability,基本業(yè)務(wù)可用性。
  • S:Soft state,柔性狀態(tài)。
  • E:Eventual consistency,最終一致性。

BASE 理論,是對 CAP 理論的延伸,是對 CAP 中的一致性和可用性進(jìn)行一個權(quán)衡的結(jié)果,理論的核心思想就是:我們無法做到強(qiáng)一致,但每個應(yīng)用都可以根據(jù)自身的業(yè)務(wù)特點(diǎn),采用適當(dāng)?shù)姆绞絹硎瓜到y(tǒng)達(dá)到最終一致性。

CAP 理論告訴我們一個分布式系統(tǒng)無法同時滿足一致性, 可用性, 分區(qū)容錯性,所以在設(shè)計(jì)上對這三點(diǎn)做取舍。剛性事務(wù)追求強(qiáng)一致性,所以犧牲了高可用性;柔性事務(wù)通過犧牲一致性換來了系統(tǒng)的高可用性。

在系統(tǒng)選擇分布式方案時,可以根據(jù)對一致性的要求進(jìn)行選擇,業(yè)務(wù)上有強(qiáng)一致性要求的場景時,優(yōu)先考慮 XA 規(guī)范的兩階段提交;業(yè)務(wù)上只需要最終一致性的場景時,可以在根據(jù)具體場景在柔性事務(wù)方案中進(jìn)行選擇。

參考

[1]分布式事務(wù)中間件TXC(http://mw.alibaba-inc.com/product-txc.html)

[2]彈力設(shè)計(jì)之補(bǔ)償事務(wù)(https://www.jianshu.com/p/8095001d79bb)

[3]分布式事務(wù)中間件ServiceComb

(http://servicecomb.apache.org/cn/docs/distributed-transactions-saga-implementation/)

[4]深入理解兩階段提交(https://sq.163yun.com/blog/article/165554812476866560)[5]Seata(https://seata.io/zh-cn/)

[6]TCC事務(wù)原理

(https://www.cnblogs.com/jajian/p/10014145.html)

[7]TCC事務(wù)異常場景(https://blog.csdn.net/dm_vincent/article/details/92432059

[8]Compensating Transaction Pattern

(https://docs.microsoft.com/en-us/azure/architecture/patterns/compensating-transaction)

[9]基于消息的分布式事務(wù)(https://www.jianshu.com/p/04bad986a4a2)

[10]分布式事務(wù)概述(http://www.tianshouzhi.com/api/tutorials/distributed_transaction/383)

[11]初識Open/X XA

(https://www.jianshu.com/p/6c1fd2420274)

[12]DTP: XA Specification

(https://pubs.opengroup.org/onlinepubs/009680699/toc.pdf)

[13]DTP Model

(https://pubs.opengroup.org/onlinepubs/009249599/toc.pdf)

【本文為51CTO專欄作者“阿里巴巴官方技術(shù)”原創(chuàng)稿件,轉(zhuǎn)載請聯(lián)系原作者】

??戳這里,看該作者更多好文??

責(zé)任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2023-09-14 15:44:46

分布式事務(wù)數(shù)據(jù)存儲

2025-04-28 00:44:04

2024-03-26 12:08:53

分布式事務(wù)存儲

2019-01-11 18:22:07

阿里巴巴技術(shù)開源

2010-07-21 13:53:41

SQL Server分

2019-07-25 15:32:35

分布式事務(wù)微服務(wù)系統(tǒng)架構(gòu)

2021-09-28 09:43:11

微服務(wù)架構(gòu)技術(shù)

2024-12-09 09:35:00

2019-09-09 10:09:51

分布式事務(wù) 數(shù)據(jù)庫

2023-11-30 07:19:08

.NET開源

2024-06-13 08:04:23

2023-03-05 18:23:38

分布式ID節(jié)點(diǎn)

2021-06-28 10:03:44

分布式數(shù)據(jù)庫架構(gòu)

2020-03-31 16:13:26

分布式事務(wù)方案TCC

2022-06-14 10:47:00

分布式事務(wù)數(shù)據(jù)

2023-08-17 10:23:07

擴(kuò)展方案

2020-09-23 09:52:01

分布式WebSocketMQ

2010-06-30 17:27:32

SQL Server數(shù)

2021-06-25 10:35:58

分布式代碼Java

2022-05-30 10:37:35

分布式事務(wù)反向補(bǔ)償
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號