偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

六種常用事務(wù)解決方案 沒有最好只有更好

開發(fā) 新聞
? 任何事務(wù)機制在實現(xiàn)時,都應(yīng)該考慮事務(wù)的ACID特性,包括:本地事務(wù)、分布式事務(wù),及時不能都很好的滿足,也要考慮支持到什么程度。

1 事務(wù)概念

在分布式系統(tǒng)中,為了保證數(shù)據(jù)的高可用,通常,我們會將數(shù)據(jù)保留多個副本(replica),這些副本會放置在不同的物理的機器上。為了對用戶提供正確的 CRUD 等語義,我們需要保證這些放置在不同物理機器上的副本是一致的。分布式事務(wù)在現(xiàn)在遍地都是分布式部署的系統(tǒng)中幾乎是必要的。

我們的項目用到了數(shù)據(jù)庫,也和事務(wù)有關(guān),我們先分析一下項目的問題,再描述一下事務(wù)。

如上圖,如果用戶打車成功,需要修改司機狀態(tài)、下單、記錄支付日志,而每個操作都是調(diào)用了不同的服務(wù),比如此時 hailtaxi-driver? 服務(wù)執(zhí)行成功了,但是 hailtaxi-order 有可能執(zhí)行失敗了,這時候如何實現(xiàn)跨服務(wù)事務(wù)回滾呢?這就要用到分布式事務(wù)。

1.1 事務(wù)簡介

事務(wù)(Transaction)是訪問并可能更新數(shù)據(jù)庫中各種數(shù)據(jù)項的一個程序執(zhí)行單元(unit)。在關(guān)系數(shù)據(jù)庫中,一個事務(wù)由一組SQL語句組成。事務(wù)應(yīng)該具有4個屬性:原子性、一致性、隔離性、持久性。這四個屬性通常稱為ACID特性。

 原子性(atomicity) :事務(wù)是一個不可分割的工作單位,事務(wù)中包括的諸操作要么都做,要么都不做。

 一致性(consistency) :事務(wù)必須是使數(shù)據(jù)庫從一個一致性狀態(tài)變到另一個一致性狀態(tài),事務(wù)的中間狀態(tài)不能被觀察到的。

 隔離性(isolation) :一個事務(wù)的執(zhí)行不能被其他事務(wù)干擾。即一個事務(wù)內(nèi)部的操作及使用的數(shù)據(jù)對并發(fā)的其他事務(wù)是隔離的,并發(fā)執(zhí)行的各個事務(wù)之間不能互相干擾。隔離性又分為四個級別:讀未提交(read uncommitted)、讀已提交(read committed,解決臟讀)、可重復(fù)讀(repeatable read,解決虛讀)、串行化(serializable,解決幻讀)。

 持久性(durability) :持久性也稱永久性(permanence),指一個事務(wù)一旦提交,它對數(shù)據(jù)庫中數(shù)據(jù)的改變就應(yīng)該是永久性的。接下來的其他操作或故障不應(yīng)該對其有任何影響。

任何事務(wù)機制在實現(xiàn)時,都應(yīng)該考慮事務(wù)的ACID特性,包括:本地事務(wù)、分布式事務(wù),及時不能都很好的滿足,也要考慮支持到什么程度。

1.2 本地事務(wù)

大多數(shù)場景下,我們的應(yīng)用都只需要操作單一的數(shù)據(jù)庫,這種情況下的事務(wù)稱之為本地事務(wù)( Local Transaction )。本地事務(wù)的ACID特性是數(shù)據(jù)庫直接提供支持。本地事務(wù)應(yīng)用架構(gòu)如下所示:

很多java應(yīng)用都整合了spring,并使用其聲明式事務(wù)管理功能來完成事務(wù)功能。一般使用的步驟如下:

? 1、配置事務(wù)管理器。spring提供了一個 PlatformTransactionManager 接口,其有2個重要的實現(xiàn)類:

 DataSourceTransactionManager? :用于支持本地事務(wù),事實上,其內(nèi)部也是通過操作 java.sql.Connection 來開啟、提交和回滾事務(wù)。

 JtaTransactionManager :用于支持分布式事務(wù),其實現(xiàn)了JTA規(guī)范,使用XA協(xié)議進行兩階段提交。需要注意的是,這只是一個代理,我們需要為其提供一個JTA provider,一般是Java EE容器提供的事務(wù)協(xié)調(diào)器(Java EE server's transaction coordinator),也可以不依賴容器,配置一個本地的JTA provider。

? 2、 在需要開啟的事務(wù)的bean的方法上添加 @Transitional 注解

可以看到,spring除了支持本地事務(wù),也支持分布式事務(wù),下面我們先對分布式事務(wù)的典型應(yīng)用場景進行介紹。

1.3 分布式事務(wù)

當(dāng)下互聯(lián)網(wǎng)發(fā)展如火如荼,絕大部分公司都進行了數(shù)據(jù)庫拆分和服務(wù)化(SOA)。在這種情況下,完成某一個業(yè)務(wù)功能可能需要橫跨多個服務(wù),操作多個數(shù)據(jù)庫。這就涉及到到了分布式事務(wù),用需要操作的資源位于多個資源服務(wù)器上,而應(yīng)用需要保證對于多個資源服務(wù)器的數(shù)據(jù)的操作,要么全部成功,要么全部失敗。本質(zhì)上來說,分布式事務(wù)就是為了保證不同資源服務(wù)器的數(shù)據(jù)一致性。

1.3.1 跨庫事務(wù)

跨庫事務(wù)指的是,一個應(yīng)用某個功能需要操作多個庫,不同的庫中存儲不同的業(yè)務(wù)數(shù)據(jù)。下圖演示了一個服務(wù)同時操作2個庫的情況:

1.3.2 分庫分表事務(wù)

通常一個庫數(shù)據(jù)量比較大或者預(yù)期未來的數(shù)據(jù)量比較大,都會進行水平拆分,也就是分庫分表。如下圖,將數(shù)據(jù)庫B拆分成了2個庫:

? 對于分庫分表的情況,一般開發(fā)人員都會使用一些數(shù)據(jù)庫中間件來降低sql操作的復(fù)雜性。如,對于sql: insert into user(id,name) values (1,"gupaoedu"),(2,"gpvp") 。這條sql是操作單庫的語法,單庫情況下,可以保證事務(wù)的一致性。

但是由于現(xiàn)在進行了分庫分表,開發(fā)人員希望將1號記錄插入分庫1,2號記錄插入分庫2。所以數(shù)據(jù)庫中間件要將其改寫為2條sql,分別插入兩個不同的分庫,此時要保證兩個庫要不都成功,要不都失敗,因此基本上所有的數(shù)據(jù)庫中間件都面臨著分布式事務(wù)的問題。

1.3.3 跨應(yīng)用事務(wù)

微服務(wù)架構(gòu)是目前一個比較一個比較火的概念。例如上面提到的一個案例,某個應(yīng)用同時操作了9個庫,這樣的應(yīng)用業(yè)務(wù)邏輯必然非常復(fù)雜,對于開發(fā)人員是極大的挑戰(zhàn),應(yīng)該拆分成不同的獨立服務(wù),以簡化業(yè)務(wù)邏輯。拆分后,獨立服務(wù)之間通過RPC框架來進行遠程調(diào)用,實現(xiàn)彼此的通信。下圖演示了一個3個服務(wù)之間彼此調(diào)用的架構(gòu):

Service A完成某個功能需要直接操作數(shù)據(jù)庫,同時需要調(diào)用Service B和Service C,而Service B又同時操作了2個數(shù)據(jù)庫,Service C也操作了一個庫。需要保證這些跨服務(wù)的對多個數(shù)據(jù)庫的操作要不都成功,要不都失敗,實際上這可能是最典型的分布式事務(wù)場景。

上述討論的分布式事務(wù)場景中,無一例外的都直接或者間接的操作了多個數(shù)據(jù)庫。如何保證事務(wù)的ACID特性,對于分布式事務(wù)實現(xiàn)方案而言,是非常大的挑戰(zhàn)。同時,分布式事務(wù)實現(xiàn)方案還必須要考慮性能的問題,如果為了嚴(yán)格保證ACID特性,導(dǎo)致性能嚴(yán)重下降,那么對于一些要求快速響應(yīng)的業(yè)務(wù),是無法接受的。

2 分布式理論

分布式事務(wù)可以有多種分類,比如柔性事務(wù)和強一致性事務(wù),這些事務(wù)操作會遵循一定的定理,比如CAP原理、BASE理論。

2.1 CAP原理

CAP 定理又被稱作布魯爾定理,是加州大學(xué)的計算機科學(xué)家布魯爾在 2000 年提出的一個猜想。2002 年,麻省理工學(xué)院的賽斯·吉爾伯特和南?!ち制姘l(fā)表了布魯爾猜想的證明,使之成為分布式計算領(lǐng)域公認的一個定理。

布魯爾在提出CAP猜想時并沒有具體定義 Consistency、Availability、Partition Tolerance 這3個詞的含義,不同資料的具體定義也有差別,為了更好地解釋,下面選擇Robert Greiner的文章《CAP Theorem》作為參考基礎(chǔ)。

CAP定理是這樣描述的:在一個分布式系統(tǒng)(指互相連接并共享數(shù)據(jù)的節(jié)點的集合)中,當(dāng)涉及讀寫操作時,只能保證一致性(Consistence)、可用性(Availability)、分區(qū)容錯性(PartitionTolerance)三者中的兩個,另外一個必須被犧牲。

Consistency、Availability、Partition Tolerance具體解釋如下:

C-Consistency 一致性

A read is guaranteed to return the most recent write for a given client.

這里并不是強調(diào)同一時刻擁有相同的數(shù)據(jù),對于系統(tǒng)執(zhí)行事務(wù)來說,在事務(wù)執(zhí)行過程中,系統(tǒng)其實處于一個不一致的狀態(tài),不同的節(jié)點的數(shù)據(jù)并不完全一致。

一致性強調(diào)客戶端讀操作能夠獲取最新的寫操作結(jié)果,是因為事務(wù)在執(zhí)行過程中,客戶端是無法讀取到未提交的數(shù)據(jù)的,只有等到事務(wù)提交后,客戶端才能讀取到事務(wù)寫入的數(shù)據(jù),而如果事務(wù)失敗則會進行回滾,客戶端也不會讀取到事務(wù)中間寫入的數(shù)據(jù)。

A-Availability 可用性

A non-failing node will return a reasonable response within a reasonable amount of time (no error or timeout).

這里強調(diào)的是合理的響應(yīng),不能超時,不能出錯。注意并沒有說“正確”的結(jié)果,例如,應(yīng)該返回 100 但實際上返回了 90,肯定是不正確的結(jié)果,但可以是一個合理的結(jié)果。

P-Partition Tolerance 分區(qū)容忍性

The system will continue to function when network partitions occur.

當(dāng)出現(xiàn) 網(wǎng)絡(luò)分區(qū) 后,系統(tǒng)能夠繼續(xù)“履行職責(zé)”。

這里 網(wǎng)絡(luò)分區(qū) 是指:

一個分布式系統(tǒng)里面,節(jié)點組成的網(wǎng)絡(luò)本來應(yīng)該是連通的。然而可能因為一些故障(節(jié)點間網(wǎng)絡(luò)連接斷開、節(jié)點宕機),使得有些節(jié)點之間不連通了,整個網(wǎng)絡(luò)就分成了幾塊區(qū)域,數(shù)據(jù)就散布在了這些不連通的區(qū)域中。

CAP 的選擇

雖然 CAP 理論定義是三個要素中只能取兩個,但放到分布式環(huán)境下來思考,我們會發(fā)現(xiàn)必須選擇 P(分區(qū)容忍)要素,因為網(wǎng)絡(luò)本身無法做到 100% 可靠,有可能出故障,所以分區(qū)是一個必然的現(xiàn)象。

為什么必須要選擇P:

如果我們選擇了 CA(一致性 + 可用性) 而放棄了 P(分區(qū)容忍性),那么當(dāng)發(fā)生分區(qū)現(xiàn)象時,為了保證 C(一致性),系統(tǒng)需要禁止寫入,當(dāng)有寫入請求時,系統(tǒng)返回 error(例如,當(dāng)前系統(tǒng)不允許寫入),這又和 A(可用性) 沖突了,因為 A(可用性)要求返回 no error 和 no timeout。

因此,分布式系統(tǒng)理論上不可能選擇 CA (一致性 + 可用性)架構(gòu), 只能選擇 CP(一致性 + 分區(qū)容忍性) 或者 AP (可用性 + 分區(qū)容忍性)架構(gòu),在一致性和可用性做折中選擇 。

針對這兩種選擇再來看一下:

1、CP - Consistency + Partition Tolerance (一致性 + 分區(qū)容忍性)

如上圖所示,因為Node1節(jié)點和Node2節(jié)點連接中斷導(dǎo)致分區(qū)現(xiàn)象,Node1節(jié)點的數(shù)據(jù)已經(jīng)更新到y(tǒng),但是Node1 和 Node2 之間的復(fù)制通道中斷,數(shù)據(jù) y 無法同步到 Node2,Node2 節(jié)點上的數(shù)據(jù)還是舊數(shù)據(jù)x。

這時客戶端C 訪問 Node2 時,Node2 需要返回 Error,提示客戶端 “系統(tǒng)現(xiàn)在發(fā)生了錯誤”,這種處理方式違

背了可用性(Availability)的要求,因此 CAP 三者只能滿足 CP。

2、AP - Availability + Partition Tolerance (可用性 + 分區(qū)容忍性)

同樣是Node2 節(jié)點上的數(shù)據(jù)還是舊數(shù)據(jù)x,這時客戶端C 訪問 Node2 時,Node2 將當(dāng)前自己擁有的數(shù)據(jù) x 返回給客戶端 了,而實際上當(dāng)前最新的數(shù)據(jù)已經(jīng)是 y 了,這就不滿足一致性(Consistency)的要求了,因此 CAP 三者只能滿足 AP。

注意:這里 Node2 節(jié)點返回 x,雖然不是一個“正確”的結(jié)果,但是一個“合理”的結(jié)果,因為 x 是舊的數(shù)據(jù),并不是一個錯亂的值,只是不是最新的數(shù)據(jù)。

值得補充的是:,CAP理論告訴我們 分布式系統(tǒng)只能選擇AP或者CP ,但實際上并不是說整個系統(tǒng)只能選擇AP或者CP,在 CAP 理論落地實踐時,我們需要將系統(tǒng)內(nèi)的數(shù)據(jù)按照不同的應(yīng)用場景和要求進行分類,每類數(shù)據(jù)選擇不同的策略(CP 還是 AP),而不是直接限定整個系統(tǒng)所有數(shù)據(jù)都是同一策略。

另外,只能選擇CP或者AP是指系統(tǒng)發(fā)生分區(qū)現(xiàn)象時無法同時保證C(一致性)和A(可用性),但不是意味著什么都不做,當(dāng)分區(qū)故障解決后,系統(tǒng)還是要保持保證CA。也就是說選了AP不意味著放棄了C,選了CP不意味著放棄了A

2.2 BASE理論

BASE 是指基本可用(Basically Available)、軟狀態(tài)( Soft State)、最終一致性( Eventual Consistency),是基于CAP定理演化而來,是對CAP中一致性和可用性權(quán)衡的結(jié)果;核心思想是即使無法做到強一致性(CAP 的一致性就是強一致性),但應(yīng)用可以采用適合的方式達到最終一致性。

BA-Basically Available基本可用

分布式系統(tǒng)在出現(xiàn)故障時,允許損失部分可用性,即保證核心可用。

這里的關(guān)鍵詞是“ 部分 ”和“ 核心 ”,實際實踐上,哪些是核心需要根據(jù)具體業(yè)務(wù)來權(quán)衡。例如登錄功能相對注冊功能更加核心,注冊不了最多影響流失一部分用戶,如果用戶已經(jīng)注冊但無法登錄,那就意味用戶無法使用系統(tǒng),造成的影響范圍更大。

S-Soft State 軟狀態(tài)

允許系統(tǒng)存在中間狀態(tài),而該中間狀態(tài)不會影響系統(tǒng)整體可用性。這里的中間狀態(tài)就是 CAP 理論中的數(shù)據(jù)不一致。

E-Eventual Consistency 最終一致性

系統(tǒng)中的所有數(shù)據(jù)副本經(jīng)過一定時間后,最終能夠達到一致的狀態(tài)。

這里的關(guān)鍵詞是“一定時間” 和 “最終”,“ 一定時間 ”和數(shù)據(jù)的特性是強關(guān)聯(lián)的,不同業(yè)務(wù)不同數(shù)據(jù)能夠容忍的不一致時間是不同的。例如支付類業(yè)務(wù)是要求秒級別內(nèi)達到一致,因為用戶時時關(guān)注;用戶發(fā)的最新微博,可以容忍30分鐘內(nèi)達到一致的狀態(tài),因為用戶短時間看不到明星發(fā)的微博是無感知的。而“ 最終 ”的含義就是不管多長時間,最終還是要達到一致性的狀態(tài)。

BASE 理論本質(zhì)上是對 CAP 的延伸和補充,更具體地說,是對 CAP 中 AP 方案的一個補充:

CP 理論是忽略延時的,而實際應(yīng)用中延時是無法避免的。

這一點就意味著完美的 CP 場景是不存在的,即使是幾毫秒的數(shù)據(jù)復(fù)制延遲,在這幾毫秒時間間隔內(nèi),系統(tǒng)是不符合 CP 要求的。因此 CAP 中的 CP 方案,實際上也是實現(xiàn)了最終一致性,只是“一定時間”是指幾毫秒而已。

AP 方案中犧牲一致性只是指發(fā)生分區(qū)故障期間,而不是永遠放棄一致性。

這一點其實就是 BASE 理論延伸的地方,分區(qū)期間犧牲一致性,但分區(qū)故障恢復(fù)后,系統(tǒng)應(yīng)該達到最終一致性。

2.3 剛?cè)崾聞?wù)

何謂剛?cè)崾聞?wù)?剛性事務(wù)它的事務(wù)是原子的,要么都成功要么都失敗,也就是需要保障ACID理論,而柔性事務(wù)只需要保障數(shù)據(jù)最終一致即可,需要遵循BASE理論。

剛性事務(wù)滿足ACID理論

柔性事務(wù)滿足BASE理論(基本可用,最終一致)

基于BASE理論的設(shè)計思想,柔性事務(wù)下,在不影響系統(tǒng)整體可用性的情況下(Basically Available 基本可用),允許系統(tǒng)存在數(shù)據(jù)不一致的中間狀態(tài)(Soft State 軟狀態(tài)),在經(jīng)過數(shù)據(jù)同步的延時之后,最終數(shù)據(jù)能夠達到一致。 并不是完全放棄了ACID,而是通過放寬一致性要求,借助本地事務(wù)來實現(xiàn)最終分布式事務(wù)一致性的同時也保證系統(tǒng)的吞吐 。

3 常用事務(wù)解決方案模型

分布式事務(wù)解決方案幾乎都是柔性事務(wù),分布式事務(wù)的實現(xiàn)有許多種,其中較經(jīng)典是由Tuxedo提出的XA分布式事務(wù)協(xié)議,XA協(xié)議包含二階段提交(2PC)和三階段提交(3PC)兩種實現(xiàn)。

其他還有 TCC、MQ 等最終一致性解決方案,至于工作中用哪種方案,需要根據(jù)業(yè)務(wù)場景選取, 2PC/3PC、TCC 數(shù)據(jù)強一致性高,而MQ是最終數(shù)據(jù)一致。

3.1 DTP模型

X/Open DTP(X/Open Distributed Transaction Processing Reference Model) 是X/Open 這個組織定義的一套分布式事務(wù)的標(biāo)準(zhǔn),也就是了定義了規(guī)范和API接口,由廠商進行具體的實現(xiàn)

X/Open DTP中的角色

AP(Application Program):應(yīng)用程序,主要是定義事務(wù)邊界以及那些組成事務(wù)的特定于應(yīng)用程序的操作。

RM(Resouces Manager):資源管理器,管理一些共享資源的自治域,如提供對諸如數(shù)據(jù)庫之類的共享資源的訪問。譬如:數(shù)據(jù)庫、文件系統(tǒng)等,并且提供了這些資源的訪問方式。

TM(Transaction Manager):事務(wù)管理器,管理全局事務(wù),協(xié)調(diào)事務(wù)的提交或者回滾,并協(xié)調(diào)故障恢復(fù)。

DTP模型里面定義了XA協(xié)議接口,TM 和 RM 通過XA接口進行雙向通信

3.2 2PC

2PC? 、 3PC? ,都是基于 XA 協(xié)議的

方案簡介

二階段提交協(xié)議(Two-phase Commit,即2PC)是常用的分布式事務(wù)解決方案,即將事務(wù)的提交過程分為兩個階段來進行處理: 準(zhǔn)備階段和提交階段。事務(wù)的發(fā)起者稱協(xié)調(diào)者,事務(wù)的執(zhí)行者稱參與者 。

在分布式系統(tǒng)里,每個節(jié)點都可以知曉自己操作的成功或者失敗,卻無法知道其他節(jié)點操作的成功或失敗。當(dāng)一個事務(wù)跨多個節(jié)點時,為了保持事務(wù)的原子性與一致性,而引入一個協(xié)調(diào)者來統(tǒng)一掌控所有參與者的操作結(jié)果,并指示它們是否要把操作結(jié)果進行真正的提交或者回滾(rollback)。

二階段提交的算法思路可以概括為: 參與者將操作成敗通知協(xié)調(diào)者,再由協(xié)調(diào)者根據(jù)所有參與者的反饋情報決定各參與者是否要提交操作還是中止操作 。

核心思想就是對每一個事務(wù)都采用先嘗試后提交的處理方式,處理后所有的讀操作都要能獲得最新的數(shù)據(jù),因此也可以將二階段提交看作是一個強一致性算法。

處理流程

簡單一點理解,可以把協(xié)調(diào)者節(jié)點比喻為帶頭大哥,參與者理解比喻為跟班小弟,帶頭大哥統(tǒng)一協(xié)調(diào)跟班小弟的任務(wù)執(zhí)行。

階段1:準(zhǔn)備階段

1、協(xié)調(diào)者向所有參與者發(fā)送事務(wù)內(nèi)容,詢問是否可以提交事務(wù),并等待所有參與者答復(fù)。

2、各參與者執(zhí)行事務(wù)操作,將undo和redo信息記入事務(wù)日志中(但不提交事務(wù))。

3、如參與者執(zhí)行成功,給協(xié)調(diào)者反饋yes,即可以提交;如執(zhí)行失敗,給協(xié)調(diào)者反饋no,即不可提交。

階段2:提交階段

如果協(xié)調(diào)者收到了參與者的失敗消息或者超時,直接給每個參與者發(fā)送回滾(rollback)消息;否則,發(fā)送提交(commit)消息;參與者根據(jù)協(xié)調(diào)者的指令執(zhí)行提交或者回滾操作,釋放所有事務(wù)處理過程中使用的鎖資源。(注意:必須在最后階段釋放鎖資源)

接下來分兩種情況分別討論提交階段的過程。

情況1,當(dāng)所有參與者均反饋yes,提交事務(wù):

  • 1、協(xié)調(diào)者向所有參與者發(fā)出正式提交事務(wù)的請求(即commit請求)。
  • 2、參與者執(zhí)行commit請求,并釋放整個事務(wù)期間占用的資源。
  • 3、各參與者向協(xié)調(diào)者反饋ack(應(yīng)答)完成的消息。
  • 4、協(xié)調(diào)者收到所有參與者反饋的ack消息后,即完成事務(wù)提交。

情況2,當(dāng)任何階段1一個參與者反饋no,中斷事務(wù):

  • 1、協(xié)調(diào)者向所有參與者發(fā)出回滾請求(即rollback請求)。
  • 2、參與者使用階段1中的undo信息執(zhí)行回滾操作,并釋放整個事務(wù)期間占用的資源。
  • 3、各參與者向協(xié)調(diào)者反饋ack完成的消息。
  • 4、協(xié)調(diào)者收到所有參與者反饋的ack消息后,即完成事務(wù)中斷。

方案總結(jié)

2PC是一個強一致性的同步阻塞協(xié)議,事務(wù)執(zhí)?過程中需要將所需資源全部鎖定,也就是俗稱的 剛性事務(wù)

2PC方案實現(xiàn)起來簡單,實際項目中使用比較少,主要因為以下問題:

  • 性能問題所有參與者在事務(wù)提交階段處于同步阻塞狀態(tài),占用系統(tǒng)資源,容易導(dǎo)致性能瓶頸。
  • 可靠性問題如果協(xié)調(diào)者存在單點故障問題,如果協(xié)調(diào)者出現(xiàn)故障,參與者將一直處于鎖定狀態(tài)。
  • 數(shù)據(jù)一致性問題在階段2中,如果發(fā)生局部網(wǎng)絡(luò)問題,一部分事務(wù)參與者收到了提交消息,另一部分事務(wù)參與者沒收到提交消息,那么就導(dǎo)致了節(jié)點之間數(shù)據(jù)的不一致。
  • 只適用于單個服務(wù)中因為使用了XA規(guī)范,只支持單體服務(wù)的跨庫分布式事務(wù),不支持跨服務(wù)間的分布式事務(wù)

3.3 3PC

方案簡介

三階段提交協(xié)議,是二階段提交協(xié)議的改進版本,與二階段提交不同的是,引入超時機制。同時在協(xié)調(diào)者和參與者中都引入超時機制( 2PC 中只有協(xié)調(diào)者有超時機制)。

三階段提交將二階段的準(zhǔn)備階段拆分為2個階段,插入了一個preCommit階段,使得原先在二階段提交中,參與者在準(zhǔn)備之后,由于協(xié)調(diào)者發(fā)生崩潰或錯誤,而導(dǎo)致參與者處于無法知曉是否提交或者中止的“不確定狀態(tài)”所產(chǎn)生的可能相當(dāng)長的延時的問題得以解決。

處理流程

階段1:canCommit

協(xié)調(diào)者向參與者發(fā)送commit請求,參與者如果可以提交就返回yes響應(yīng)(參與者不執(zhí)行事務(wù)操作),否則返回no響應(yīng):

  • 1、協(xié)調(diào)者向所有參與者發(fā)出包含事務(wù)內(nèi)容的canCommit請求,詢問是否可以提交事務(wù),并等待所有參與者答復(fù)。
  • 2、參與者收到canCommit請求后,如果認為可以執(zhí)行事務(wù)操作,則反饋yes并進入預(yù)備狀態(tài),否則反饋no。

階段2:preCommit

協(xié)調(diào)者根據(jù)階段1 canCommit參與者的反應(yīng)情況來決定是否可以基于事務(wù)的preCommit操作。根據(jù)響應(yīng)情況,有以下兩種可能。

情況1,階段1所有參與者均反饋yes,參與者預(yù)執(zhí)行事務(wù):

  • 1、協(xié)調(diào)者向所有參與者發(fā)出preCommit請求,進入準(zhǔn)備階段。
  • 2、參與者收到preCommit請求后,執(zhí)行事務(wù)操作,將undo和redo信息記入事務(wù)日志中(但不提交事務(wù))。
  • 3、各參與者向協(xié)調(diào)者反饋ack響應(yīng)或no響應(yīng),并等待最終指令。

情況2,階段1任何一個參與者反饋no,或者等待超時后協(xié)調(diào)者尚無法收到所有參與者的反饋,即中斷事務(wù):

  • 1、協(xié)調(diào)者向所有參與者發(fā)出abort請求。
  • 2、無論收到協(xié)調(diào)者發(fā)出的abort請求,或者在等待協(xié)調(diào)者請求過程中出現(xiàn)超時,參與者均會中斷事務(wù)。

?階段3:do Commit

該階段進行真正的事務(wù)提交,也可以分為以下兩種情況:

情況1:階段2所有參與者均反饋ack響應(yīng),執(zhí)行真正的事務(wù)提交:

  • 1、如果協(xié)調(diào)者處于工作狀態(tài),則向所有參與者發(fā)出do Commit請求。
  • 2、參與者收到do Commit請求后,會正式執(zhí)行事務(wù)提交,并釋放整個事務(wù)期間占用的資源。
  • 3、各參與者向協(xié)調(diào)者反饋ack完成的消息。
  • 4、協(xié)調(diào)者收到所有參與者反饋的ack消息后,即完成事務(wù)提交。

階段2任何一個參與者反饋no,或者等待超時后協(xié)調(diào)者尚無法收到所有參與者的反饋,即中斷事務(wù):

  • 1、如果協(xié)調(diào)者處于工作狀態(tài),向所有參與者發(fā)出abort請求。
  • 2、參與者使用階段1中的undo信息執(zhí)行回滾操作,并釋放整個事務(wù)期間占用的資源。
  • 3、各參與者向協(xié)調(diào)者反饋ack完成的消息。
  • 4、協(xié)調(diào)者收到所有參與者反饋的ack消息后,即完成事務(wù)中斷

注意:進入階段3后,無論協(xié)調(diào)者出現(xiàn)問題,或者協(xié)調(diào)者與參與者網(wǎng)絡(luò)出現(xiàn)問題,都會導(dǎo)致參與者無法接收到協(xié)調(diào)者發(fā)出的do Commit請求或abort請求。此時,參與者都會在等待超時之后,繼續(xù)執(zhí)行事務(wù)提交。

階段三 只允許成功不允許失敗,如果服務(wù)器宕機或者停電,因為記錄的階段二的數(shù)據(jù),重啟服務(wù)后在提交事務(wù),所以,到了階段三,失敗了也不進行回滾, 只允許成功 。

方案總結(jié)

優(yōu)點

相比二階段提交,三階段提交降低了阻塞范圍,在等待超時后協(xié)調(diào)者或參與者會中斷事務(wù)。避免了協(xié)調(diào)者單點問題,階段3中協(xié)調(diào)者出現(xiàn)問題時,參與者會繼續(xù)提交事務(wù)。

缺點

數(shù)據(jù)不一致問題依然存在,當(dāng)在參與者收到preCommit請求后等待do commite指令時,此時如果協(xié)調(diào)者請求中斷事務(wù),而協(xié)調(diào)者無法與參與者正常通信,會導(dǎo)致參與者繼續(xù)提交事務(wù),造成數(shù)據(jù)不一致。

3.4 TCC

方案簡介

TCC(Try-Confirm-Cancel)的概念,最早是由Pat Helland于2007年發(fā)表的一篇名為《Life beyond Distributed Transactions:an Apostate’s Opinion》的論文提出。

TCC是服務(wù)化的二階段編程模型,其Try、Confirm、Cancel 3個方法均由業(yè)務(wù)編碼實現(xiàn);

  • Try操作作為一階段,負責(zé)資源的檢查和預(yù)留。
  • Confirm操作作為二階段提交操作,執(zhí)行真正的業(yè)務(wù)。
  • Cancel是預(yù)留資源的取消。

TCC事務(wù)的Try、Confirm、Cancel可以理解為SQL事務(wù)中的Lock、Commit、Rollback。

TCC? 為在業(yè)務(wù)層編寫代碼實現(xiàn)的兩階段提交。 TCC? 分別指 Try? 、 Confirm? 、 Cancel ,一個業(yè)務(wù)操作要對應(yīng)的寫這三個方法。

處理流程

為了方便理解,下面以電商下單為例進行方案解析,這里把整個過程簡單分為扣減庫存,訂單創(chuàng)建2個步驟,庫存服務(wù)和訂單服務(wù)分別在不同的服務(wù)器節(jié)點上。

階段1:Try 階段

從執(zhí)行階段來看,與傳統(tǒng)事務(wù)機制中業(yè)務(wù)邏輯相同。但從業(yè)務(wù)角度來看,卻不一樣。TCC機制中的Try僅是一個初步操作,它和后續(xù)的確認一起才能真正構(gòu)成一個完整的業(yè)務(wù)邏輯,這個階段主要完成:

  • 完成所有業(yè)務(wù)檢查( 一致性 )
  • 預(yù)留必須業(yè)務(wù)資源( 準(zhǔn)隔離性 )
  • Try 嘗試執(zhí)行業(yè)務(wù)TCC事務(wù)機制以初步操作(Try)為中心的,確認操作(Confirm)和取消操作(Cancel)都是圍繞初步操作(Try)而展開。因此,Try階段中的操作,其保障性是最好的,即使失敗,仍然有取消操作(Cancel)可以將其執(zhí)行結(jié)果撤銷。

假設(shè)商品庫存為100,購買數(shù)量為2,這里檢查和更新庫存的同時,凍結(jié)用戶購買數(shù)量的庫存,同時創(chuàng)建訂單,訂單狀態(tài)為待確認。

階段2:Confirm / Cancel 階段

根據(jù)Try階段服務(wù)是否全部正常執(zhí)行,繼續(xù)執(zhí)行確認操作(Confirm)或取消操作(Cancel)。

Confirm:確認

當(dāng)Try階段服務(wù)全部正常執(zhí)行, 執(zhí)行確認業(yè)務(wù)邏輯操作

這里使用的資源一定是Try階段預(yù)留的業(yè)務(wù)資源。在TCC事務(wù)機制中認為,如果在Try階段能正常的預(yù)留資源,那Confirm一定能完整正確的提交。Confirm階段也可以看成是對Try階段的一個補充,Try+Confirm一起組成了一個完整的業(yè)務(wù)邏輯。

Cancel:取消

當(dāng)Try階段存在服務(wù)執(zhí)行失敗, 進入Cancel階段

Cancel取消執(zhí)行,釋放Try階段預(yù)留的業(yè)務(wù)資源,上面的例子中,Cancel操作會把凍結(jié)的庫存釋放,并更新訂單狀態(tài)為取消。

方案總結(jié)

TCC事務(wù)機制相對于傳統(tǒng)事務(wù)機制(X/Open XA),TCC事務(wù)機制相比于上面介紹的XA事務(wù)機制,有以下優(yōu)點:

  • 性能提升具體業(yè)務(wù)來實現(xiàn)控制資源鎖的粒度變小,不會鎖定整個資源。
  • 數(shù)據(jù)最終一致性基于Confirm和Cancel的冪等性,保證事務(wù)最終完成確認或者取消,保證數(shù)據(jù)的一致性。
  • 可靠性解決了XA協(xié)議的協(xié)調(diào)者單點故障問題,由主業(yè)務(wù)方發(fā)起并控制整個業(yè)務(wù)活動,業(yè)務(wù)活動管理器也變成多點,引入集群。

缺點:

TCC的Try、Confirm和Cancel操作功能要按具體業(yè)務(wù)來實現(xiàn),業(yè)務(wù)耦合度較高,提高了開發(fā)成本。

3.5 本地消息表

方案簡介

本地消息表的方案最初是由ebay提出,核心思路是將分布式事務(wù)拆分成本地事務(wù)進行處理。

方案通過在事務(wù)主動發(fā)起方額外新建事務(wù)消息表,事務(wù)發(fā)起方處理業(yè)務(wù)和記錄事務(wù)消息在本地事務(wù)中完成,輪詢事務(wù)消息表的數(shù)據(jù)發(fā)送事務(wù)消息,事務(wù)被動方基于消息中間件消費事務(wù)消息表中的事務(wù)。

這樣設(shè)計可以避免” 業(yè)務(wù)處理成功 + 事務(wù)消息發(fā)送失敗 “,或” 業(yè)務(wù)處理失敗 + 事務(wù)消息發(fā)送成功 “的棘手情況出現(xiàn),保證2個系統(tǒng)事務(wù)的數(shù)據(jù)一致性。

處理流程

下面把分布式事務(wù)最先開始處理的事務(wù)方成為事務(wù)主動方,在事務(wù)主動方之后處理的業(yè)務(wù)內(nèi)的其他事務(wù)成為事務(wù)被動方。

為了方便理解,下面繼續(xù)以電商下單為例進行方案解析,這里把整個過程簡單分為扣減庫存,訂單創(chuàng)建2個步驟,庫存服務(wù)和訂單服務(wù)分別在不同的服務(wù)器節(jié)點上,其中庫存服務(wù)是事務(wù)主動方,訂單服務(wù)是事務(wù)被動方。

事務(wù)的主動方需要額外新建事務(wù)消息表,用于記錄分布式事務(wù)的消息的發(fā)生、處理狀態(tài)。

整個業(yè)務(wù)處理流程如下:

步驟1 事務(wù)主動方處理本地事務(wù)。

事務(wù)主動方在本地事務(wù)中處理業(yè)務(wù)更新操作和寫消息表操作。

上面例子中庫存服務(wù)階段在本地事務(wù)中完成扣減庫存和寫消息表(圖中1、2)。

步驟2 事務(wù)主動方通過消息中間件,通知事務(wù)被動方處理事務(wù)通知事務(wù)待消息。

消息中間件可以基于Kafka、RocketMQ消息隊列,事務(wù)主動方法主動寫消息到消息隊列,事務(wù)消費方消費并處理消息隊列中的消息。

上面例子中,庫存服務(wù)把事務(wù)待處理消息寫到消息中間件,訂單服務(wù)消費消息中間件的消息,完成新增訂單(圖中3 - 5)。

步驟3 事務(wù)被動方通過消息中間件,通知事務(wù)主動方事務(wù)已處理的消息。

上面例子中,訂單服務(wù)把事務(wù)已處理消息寫到消息中間件,庫存服務(wù)消費中間件的消息,并將事務(wù)消息的狀態(tài)更新為已完成(圖中6 - 8)

為了數(shù)據(jù)的一致性,當(dāng)處理錯誤需要重試,事務(wù)發(fā)送方和事務(wù)接收方相關(guān)業(yè)務(wù)處理需要支持冪等。具體保存一致性的容錯處理如下:

1、當(dāng)步驟1處理出錯,事務(wù)回滾,相當(dāng)于什么都沒發(fā)生。

2、當(dāng)步驟2、步驟3處理出錯,由于未處理的事務(wù)消息還是保存在事務(wù)發(fā)送方,事務(wù)發(fā)送方可以定時輪詢?yōu)槌瑫r消息數(shù)據(jù),再次發(fā)送的消息中間件進行處理。事務(wù)被動方消費事務(wù)消息重試處理。

3、如果是業(yè)務(wù)上的失敗,事務(wù)被動方可以發(fā)消息給事務(wù)主動方進行回滾。

4、如果多個事務(wù)被動方已經(jīng)消費消息,事務(wù)主動方需要回滾事務(wù)時需要通知事務(wù)被動方回滾。

方案總結(jié)

方案的優(yōu)點如下:

  • 從應(yīng)用設(shè)計開發(fā)的角度實現(xiàn)了消息數(shù)據(jù)的可靠性,消息數(shù)據(jù)的可靠性不依賴于消息中間件,弱化了對MQ中間件特性的依賴。
  • 方案輕量,容易實現(xiàn)。

缺點如下:

  • 與具體的業(yè)務(wù)場景綁定,耦合性強,不可公用。
  • 消息數(shù)據(jù)與業(yè)務(wù)數(shù)據(jù)同庫,占用業(yè)務(wù)系統(tǒng)資源。
  • 業(yè)務(wù)系統(tǒng)在使用關(guān)系型數(shù)據(jù)庫的情況下,消息服務(wù)性能會受到關(guān)系型數(shù)據(jù)庫并發(fā)性能的局限

3.6 MQ事務(wù)

MQ事務(wù)保證最終一致性。

方案簡介

基于MQ的分布式事務(wù)方案其實是對本地消息表的封裝,將本地消息表存于MQ 內(nèi)部,其他方面的協(xié)議基本與本地消息表一致。

處理流程

下面主要基于RocketMQ4.3之后的版本介紹MQ的分布式事務(wù)方案。

在本地消息表方案中,保證事務(wù)主動方發(fā)寫業(yè)務(wù)表數(shù)據(jù)和寫消息表數(shù)據(jù)的一致性是基于數(shù)據(jù)庫事務(wù),RocketMQ的事務(wù)消息相對于普通MQ,相對于提供了2PC的提交接口,方案如下:

正常情況——事務(wù)主動方發(fā)消息

這種情況下,事務(wù)主動方服務(wù)正常,沒有發(fā)生故障,發(fā)消息流程如下:

1、發(fā)送方向 MQ服務(wù)端(MQ Server)發(fā)送half消息。

2、MQ Server 將消息持久化成功之后,向發(fā)送方 ACK 確認消息已經(jīng)發(fā)送成功。

3、發(fā)送方開始執(zhí)行本地事務(wù)邏輯。

4、發(fā)送方根據(jù)本地事務(wù)執(zhí)行結(jié)果向 MQ Server 提交二次確認(commit 或是 rollback)。

5、MQ Server 收到 commit 狀態(tài)則將半消息標(biāo)記為可投遞,訂閱方最終將收到該消息;MQ Server 收到 rollback 狀態(tài)則刪除半消息,訂閱方將不會接受該消息。

異常情況——事務(wù)主動方消息恢復(fù)

在斷網(wǎng)或者應(yīng)用重啟等異常情況下,圖中第4步提交的二次確認超時未到達 MQ Server,此時處理邏輯如下:

  • 5、MQ Server 對該消息發(fā)起消息回查。
  • 6、發(fā)送方收到消息回查后,需要檢查對應(yīng)消息的本地事務(wù)執(zhí)行的最終結(jié)果。
  • 7、發(fā)送方根據(jù)檢查得到的本地事務(wù)的最終狀態(tài)再次提交二次確認
  • 8、MQ Server基于commit / rollback 對消息進行投遞或者刪除

介紹完RocketMQ的事務(wù)消息方案后,由于前面已經(jīng)介紹過本地消息表方案,這里就簡單介紹RocketMQ分布式事務(wù):

事務(wù)主動方基于MQ通信通知事務(wù)被動方處理事務(wù),事務(wù)被動方基于MQ返回處理結(jié)果。

如果事務(wù)被動方消費消息異常,需要不斷重試,業(yè)務(wù)處理邏輯需要保證冪等。

如果是事務(wù)被動方業(yè)務(wù)上的處理失敗,可以通過MQ通知事務(wù)主動方進行補償或者事務(wù)回滾。

方案總結(jié)

相比本地消息表方案,MQ事務(wù)方案優(yōu)點是:

  • 消息數(shù)據(jù)獨立存儲 ,降低業(yè)務(wù)系統(tǒng)與消息系統(tǒng)之間的耦合。
  • 吞吐量優(yōu)于使用本地消息表方案。

缺點是:

  • 一次消息發(fā)送需要兩次網(wǎng)絡(luò)請求(half消息 + commit/rollback消息)
  • 業(yè)務(wù)處理服務(wù)需要實現(xiàn)消息狀態(tài)回查接口
責(zé)任編輯:張燕妮 來源: 傳智教育博學(xué)谷 - 狂野架構(gòu)師
相關(guān)推薦

2021-06-25 10:35:58

分布式代碼Java

2019-01-17 10:58:52

JS異步編程前端

2022-12-06 10:39:43

Spring事務(wù)失效

2025-05-06 00:00:05

MySQLES協(xié)同

2025-05-19 00:02:00

數(shù)據(jù)脫敏加密算法數(shù)據(jù)庫

2022-05-24 10:43:02

延時消息分布式MQ

2024-03-26 12:08:53

分布式事務(wù)存儲

2025-03-17 08:07:11

2021-12-08 13:20:39

Bean拷貝工具Java

2017-08-02 14:17:08

前端asyncawait

2017-06-26 10:35:58

前端JavaScript繼承方式

2025-04-29 04:00:00

分布式事務(wù)事務(wù)消息

2019-08-02 08:50:47

API架構(gòu)微服務(wù)

2010-03-15 17:12:52

Python字典

2019-07-25 15:32:35

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

2023-05-26 07:19:49

Spring聲明式事務(wù)

2019-12-03 12:16:36

物聯(lián)網(wǎng)ZigBee藍牙低功耗

2023-11-28 15:32:30

負載均衡算法

2024-11-20 15:24:49

2024-05-22 19:10:18

跨域Web開發(fā)
點贊
收藏

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