分散式事務概述及大廠通用解決方案

猿小二1發表於2020-12-29

1.0 分散式事務概述 2018-02-05 02:05:26 32,685 16 1、事務簡介

  事務(Transaction)是訪問並可能更新資料庫中各種資料項的一個程式執行單元(unit)。在關聯式資料庫中,一個事務由一組SQL語句組成。事務應該具有4個屬性:原子性、一致性、隔離性、永續性。這四個屬性通常稱為ACID特性。

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

 一致性(consistency):事務必須是使資料庫從一個一致性狀態變到另一個一致性狀態,事務的中間狀態不能被觀察到的。

 隔離性(isolation):一個事務的執行不能被其他事務干擾。即一個事務內部的操作及使用的資料對併發的其他事務是隔離的,併發執行的各個事務之間不能互相干擾。隔離性又分為四個級別:讀未提交(read uncommitted)、讀已提交(read committed,解決髒讀)、可重複讀(repeatable read,解決虛讀)、序列化(serializable,解決幻讀)。

永續性(durability):永續性也稱永久性(permanence),指一個事務一旦提交,它對資料庫中資料的改變就應該是永久性的。接下來的其他操作或故障不應該對其有任何影響。

任何事務機制在實現時,都應該考慮事務的ACID特性,包括:本地事務、分散式事務,及時不能都很好的滿足,也要考慮支援到什麼程度。

2 本地事務

    大多數場景下,我們的應用都只需要操作單一的資料庫,這種情況下的事務稱之為本地事務(Local Transaction)。本地事務的ACID特性是資料庫直接提供支援。本地事務應用架構如下所示:

file 在JDBC程式設計中,我們通過java.sql.Connection物件來開啟、關閉或者提交事務。程式碼如下所示:

Connection conn = ... //獲取資料庫連線 conn.setAutoCommit(false); //開啟事務 try{ //...執行增刪改查sql conn.commit(); //提交事務 }catch (Exception e) { conn.rollback();//事務回滾 }finally{ conn.close();//關閉連結 }

此外,很多java應用都整合了spring,並使用其宣告式事務管理功能來完成事務功能。一般使用的步驟如下:

1、配置事務管理器。spring提供了一個PlatformTransactionManager介面,其有2個重要的實現類:

    DataSourceTransactionManager:用於支援本地事務,事實上,其內部也是通過操作java.sql.Connection來開啟、提交和回滾事務。

    JtaTransactionManager:用於支援分散式事務,其實現了JTA規範,使用XA協議進行兩階段提交。需要注意的是,這只是一個代理,我們需要為其提供一個JTA provider,一般是Java EE容器提供的事務協調器(Java EE server's transaction coordinator),也可以不依賴容器,配置一個本地的JTA provider。

2、 在需要開啟的事務的bean的方法上新增@Transitional註解

可以看到,spring除了支援本地事務,也支援分散式事務,下面我們先對分散式事務的典型應用場景進行介紹。

3 分散式事務典型場景

當下網際網路發展如火如荼,絕大部分公司都進行了資料庫拆分和服務化(SOA)。在這種情況下,完成某一個業務功能可能需要橫跨多個服務,操作多個資料庫。這就涉及到到了分散式事務,用需要操作的資源位於多個資源伺服器上,而應用需要保證對於多個資源伺服器的資料的操作,要麼全部成功,要麼全部失敗。本質上來說,分散式事務就是為了保證不同資源伺服器的資料一致性。

典型的分散式事務場景:

1、跨庫事務

跨庫事務指的是,一個應用某個功能需要操作多個庫,不同的庫中儲存不同的業務資料。筆者見過一個相對比較複雜的業務,一個業務中同時操作了9個庫。下圖演示了一個服務同時操作2個庫的情況: 

file 2、分庫分表

通常一個庫資料量比較大或者預期未來的資料量比較大,都會進行水平拆分,也就是分庫分表。如下圖,將資料庫B拆分成了2個庫: 

file 對於分庫分表的情況,一般開發人員都會使用一些資料庫中介軟體來降低sql操作的複雜性。如,對於sql:insert into user(id,name) values (1,"tianshouzhi"),(2,"wangxiaoxiao")。這條sql是操作單庫的語法,單庫情況下,可以保證事務的一致性。

但是由於現在進行了分庫分表,開發人員希望將1號記錄插入分庫1,2號記錄插入分庫2。所以資料庫中介軟體要將其改寫為2條sql,分別插入兩個不同的分庫,此時要保證兩個庫要不都成功,要不都失敗,因此基本上所有的資料庫中介軟體都面臨著分散式事務的問題。

3、服務化(SOA)

微服務架構是目前一個比較一個比較火的概念。例如上面筆者提到的一個案例,某個應用同時操作了9個庫,這樣的應用業務邏輯必然非常複雜,對於開發人員是極大的挑戰,應該拆分成不同的獨立服務,以簡化業務邏輯。拆分後,獨立服務之間通過RPC框架來進行遠端呼叫,實現彼此的通訊。下圖演示了一個3個服務之間彼此呼叫的架構:

file

Service A完成某個功能需要直接運算元據庫,同時需要呼叫Service B和Service C,而Service B又同時操作了2個資料庫,Service C也操作了一個庫。需要保證這些跨服務的對多個資料庫的操作要不都成功,要不都失敗,實際上這可能是最典型的分散式事務場景。

小結:上述討論的分散式事務場景中,無一例外的都直接或者間接的操作了多個資料庫。如何保證事務的ACID特性,對於分散式事務實現方案而言,是非常大的挑戰。同時,分散式事務實現方案還必須要考慮效能的問題,如果為了嚴格保證ACID特性,導致效能嚴重下降,那麼對於一些要求快速響應的業務,是無法接受的。

4 X/Open DTP模型與XA規範 X/Open,即現在的open group,是一個獨立的組織,主要負責制定各種行業技術標準。官網地址:http://www.opengroup.org/。X/Open組織主要由各大知名公司或者廠商進行支援,這些組織不光遵循X/Open組織定義的行業技術標準,也參與到標準的制定。下圖展示了open group目前主要成員(官網截圖):

file 可以看到,中國人的驕傲,華為,赫然在列!!!此處應該有掌聲。

就分散式事務處理(Distributed Transaction Processing,簡稱DTP)而言,X/Open主要提供了以下參考文件:

DTP 參考模型: < >

DTP XA規範: << Distributed Transaction Processing: The XA Specification>>

4.1 DTP模型

1、模型元素

在< >第3版中,規定了構成DTP模型的5個基本元素:

應用程式(Application Program ,簡稱AP):用於定義事務邊界(即定義事務的開始和結束),並且在事務邊界內對資源進行操作。

資源管理器(Resource Manager,簡稱RM):如資料庫、檔案系統等,並提供訪問資源的方式。

事務管理器(Transaction Manager ,簡稱TM):負責分配事務唯一標識,監控事務的執行進度,並負責事務的提交、回滾等。

通訊資源管理器(Communication Resource Manager,簡稱CRM):控制一個TM域(TM domain)內或者跨TM域的分散式應用之間的通訊。

通訊協議(Communication Protocol,簡稱CP):提供CRM提供的分散式應用節點之間的底層通訊服務。

其中由於通訊資源管理器(Communication Resource Manager)和通訊協議(Communication Protocol)是一對好基友,從Communication Protocol的簡稱CP上就可以看出來,兩個元素的關係不一般,因此有的文章在介紹DTP模型元素時,只提到了通訊資源管理器....

2、模型例項(Instance of the Model)

一個DTP模型例項,至少有3個組成部分:AP、RMs、TM。如下所示: 

file 這張圖類似於我們之前提到的跨庫事務的概念,即單個應用需要操作多個庫。在這裡就是一個AP需要操作多個RM上的資源。AP通過TM來宣告一個全域性事務,然後操作不同的RM上的資源,最後通知TM來提交或者回滾全域性事務。

  特別的,如果分散式事務需要跨多個應用,類似於我們前面的提到的分散式事務場景中的服務化,那麼每個模型例項中,還需要額外的加入一個通訊資源管理器CRM。

下圖中演示了2個模型例項,如何通過CRM來進行通訊: 

file CRM作為多個模型例項之間通訊的橋樑,主要作用如下:

基本的通訊能力:從這個角度,可以將CRM類比為RPC框架,模型例項之間通過RPC呼叫實現彼此的通訊。這一點體現在AP、CRM之間的連線。

事務傳播能力:與傳統RPC框架不同的是,CRM底層採用OSI TP(Open Systems Interconnection — Distributed Transaction Processing)通訊服務,因此CRM具備事務傳播能力。這一點體現TM、CRM之間的連線。

2、事務管理器作用域 (TM domain)

    一個TM domain中由一個或者多個模型例項組成,這些模型例項使用的都是同一個TM,但是操作的RMs各不相同,由TM來統一協調這些模型例項共同參與形成的全域性事務(global transaction)。

下圖展示了一個由四個模型例項組成的TM Domain,這四個模型例項使用的都是同一個事務管理器TM1。

file TM domain只是列出了最終參與到一個全域性事務中,有哪些模型例項,並不關心這些模型例項之間的關係。這就好比,有一個班級,我們只是想知道這個班級中每位同學的名字,但是並不是關心誰是班長、誰是學習委員等。

不過顯然的,當一個TM domain中存在多個模型例項時,模型例項彼此之間存在一定的層級呼叫關係。這就是全域性事務的樹形結構。 

3 全域性事務樹形結構(Global Transaction Tree Structure)

當一個TM domain中,存在多個模型例項時,會形成一種樹形條用關係,如下圖所示:

file

其中:

發起分散式事務的模型例項稱之為root節點,或者稱之為事務的發起者,其他的模型例項可以統稱為事務的參與者。事務發起者負責開啟整個全域性事務,事務參與者各自負責執行自己的事務分支。

而從模型例項之間的相互呼叫關係來說,呼叫方稱之為上游節點(Superior Node),被呼叫方稱之為下游節點(Subordinate Node)。

小結:通過對DTP模型的介紹,我們可以看出來,之前提到的分散式事務的幾種典型場景實際上在DTP模型中都包含了,甚至比我們考慮的還複雜。DTP模型從最早提出到現在已經有接近30年,到如今依然適用,不得不佩服模型的設計者是很有遠見的。

4.2 XA規範

 在DTP本地模型例項中,由AP、RMs和TM組成,不需要其他元素。AP、RM和TM之間,彼此都需要進行互動,如下圖所示: 

file 這張圖中(1)表示AP-RM的互動介面,(2)表示AP-TM的互動介面,(3)表示RM-TM的互動介面。關於這張圖,XA規範有以下描述:

The subject of this X/Open specification is interface (3) in the diagram above, the XA interface by which TMs and RMs interact.

For more details on this model and diagram, including detailed definitions of each component, see the referenced DTP guide.

也就是說XA規範的最主要的作用是,就是定義了RM-TM的互動介面,下圖更加清晰了演示了XA規範在DTP模型中發揮作用的位置,從下圖中可以看出來,XA僅僅出現在RM和TM的連線上。

file

XA規範除了定義的RM-TM互動的介面(XA Interface)之外,還對兩階段提交協議進行了優化。 一些讀者可能會誤認為兩階段提交協議是在XA規範中提出來的。事實上: 兩階段協議(two-phase commit)是在OSI TP標準中提出的;在DTP參考模型(<<Distributed Transaction Processing: Reference Model>>)中,指定了全域性事務的提交要使用two-phase commit協議;而XA規範(<< Distributed Transaction Processing: The XA Specification>>)只是定義了兩階段提交協議中需要使用到的介面,也就是上述提到的RM-TM互動的介面,因為兩階段提交過程中的參與方,只有TM和RMs。參見<<Distributed Transaction Processing: Reference Model>> 第3版 2.1節,原文如下: 

Commitment Protocol

A commitment protocol is the synchronisation that occurs at transaction completion. The X/Open DTP Model follows the two-phase commit with presumed rollback1 protocol defined in the referenced OSI TP standards. A description of the basic protocol is given in Section 3.4.3 on page 13. In certain cases, a global transaction may be completed heuristically. Heuristic transaction completion is described in Section 3.4.5 on page 14.

4.2.1 XA Interface

XA規範中定義的RM 和 TM互動的介面如下圖所示:

file

關於這些介面的詳細解釋,可以直接參考XA規範。後面在講解到mysql對XA事務的支援時,我們也會使用到部分命令。

4.2.2 兩階段提交協議(2PC)

兩階段提交協議(Two Phase Commit)不是在XA規範中提出,但是XA規範對其進行了優化,因此統一放到這裡進行講解。而從字面意思來理解,Two Phase Commit,就是將提交(commit)過程劃分為2個階段(Phase):

file

In Phase 1, the TM asks all RMs to prepare to commit (or prepare) transaction branches. This asks whether the RM can guarantee its ability to commit the transaction branch. An RM may have to query other entities internal to that RM.

If an RM can commit its work, it records stably the information it needs to do so, then replies affirmatively. A negative reply reports failure for any reason. After making a negative reply and rolling back its work, the RM can discard any knowledge it has of the transaction branch.

In Phase 2, the TM issues all RMs an actual request to commit or roll back the transaction branch, as the case may be. (Before issuing requests to commit, the TM stably records the fact that it decided to commit, as well as a list of all involved RMs.) All RMs commit or roll back changes to shared resources and then return status to the TM. The TM can then discard its knowledge of the global transaction.

階段1:

TM通知各個RM準備提交它們的事務分支。如果RM判斷自己進行的工作可以被提交,那就就對工作內容進行持久化,再給TM肯定答覆;要是發生了其他情況,那給TM的都是否定答覆。在傳送了否定答覆並回滾了已經的工作後,RM就可以丟棄這個事務分支資訊。

以mysql資料庫為例,在第一階段,事務管理器向所有涉及到的資料庫伺服器發出prepare"準備提交"請求,資料庫收到請求後執行資料修改和日誌記錄等處理,處理完成後只是把事務的狀態改成"可以提交",然後把結果返回給事務管理器。

階段2

TM根據階段1各個RM prepare的結果,決定是提交還是回滾事務。如果所有的RM都prepare成功,那麼TM通知所有的RM進行提交;如果有RM prepare失敗的話,則TM通知所有RM回滾自己的事務分支。

  以mysql資料庫為例,如果第一階段中所有資料庫都prepare成功,那麼事務管理器向資料庫伺服器發出"確認提交"請求,資料庫伺服器把事務的"可以提交"狀態改為"提交完成"狀態,然後返回應答。如果在第一階段內有任何一個資料庫的操作發生了錯誤,或者事務管理器收不到某個資料庫的回應,則認為事務失敗,回撤所有資料庫的事務。資料庫伺服器收不到第二階段的確認提交請求,也會把"可以提交"的事務回撤。

XA規範對兩階段提交協議有2點優化:

Protocol Optimisations

• Read-only

   An RM can respond to the TM’s prepare request by asserting that the RM was not asked to update shared resources in this transaction branch. This response concludes the RM’s involvement in the transaction; the Phase 2 dialogue between the TM and this RM does not occur. The TM need not stably record, in its list of participating RMs, an RM that asserts a read-only role in the global transaction.

However, if the RM returns the read-only optimisation before all work on the global transaction is prepared, global serialisability1 cannot be guaranteed. This is because the RM may release transaction context, such as read locks, before all application activity for that global transaction is finished.

  1. One-phase Commit

    A TM can use one-phase commit if it knows that there is only one RM anywhere in the DTP system that is making changes to shared resources. In this optimisation, the TM makes its Phase 2 commit request without having made a Phase 1 prepare request. Since the RM decides the outcome of the transaction branch and forgets about the transaction branch before returning to the TM, there is no need for the TM to record stably these global transactions and, in some failure cases, the TM may not know the outcome.

只讀斷言

在Phase 1中,RM可以斷言“我這邊不涉及資料增刪改”來答覆TM的prepare請求,從而讓這個RM脫離當前的全域性事務,從而免去了Phase 2。

這種優化發生在其他RM都完成prepare之前的話,使用了只讀斷言的RM早於AP其他動作(比如說這個RM返回那些只讀資料給AP)前,就釋放了相關資料的上下文(比如讀鎖之類的),這時候其他全域性事務或者本地事務就有機會去改變這些資料,結果就是無法保障整個系統的可序列化特性——通俗點說那就會有髒讀的風險。

一階段提交

如果需要增刪改的資料都在同一個RM上,TM可以使用一階段提交——跳過兩階段提交中的Phase 1,直接執行Phase 2。

這種優化的本質是跳過Phase 1,RM自行決定了事務分支的結果,並且在答覆TM前就清除掉事務分支資訊。對於這種優化的情況,TM實際上也沒有必要去可靠的記錄全域性事務的資訊,在一些異常的場景下,此時TM可能不知道事務分支的執行結果。

4.2.3 兩階段提交協議(2PC)存在的問題

二階段提交看起來確實能夠提供原子性的操作,但是不幸的是,二階段提交還是有幾個缺點的:

1、同步阻塞問題。兩階段提交方案下全域性事務的ACID特性,是依賴於RM的。例如mysql5.7官方文件關於對XA分散式事務的支援有以下介紹:

https://dev.mysql.com/doc/refman/5.7/en/xa.html

A global transaction involves several actions that are transactional in themselves, but that all must either complete successfully as a group, or all be rolled back as a group. In essence, this extends ACID properties “up a level” so that multiple ACID transactions can be executed in concert as components of a global operation that also has ACID properties. (As with nondistributed transactions, SERIALIZABLE may be preferred if your applications are sensitive to read phenomena. REPEATABLE READ may not be sufficient for distributed transactions.)

大致含義是說,一個全域性事務內部包含了多個獨立的事務分支,這一組事務分支要不都成功,要不都失敗。各個事務分支的ACID特性共同構成了全域性事務的ACID特性。也就是將單個事務分支的支援的ACID特性提升一個層次(up a level)到分散式事務的範疇。

括號中的內容的意思是: 即使在非分佈事務中(即本地事務),如果對操作讀很敏感,我們也需要將事務隔離級別設定為SERIALIZABLE。而對於分散式事務來說,更是如此,可重複讀隔離級別不足以保證分散式事務一致性。

也就是說,如果我們使用mysql來支援XA分散式事務的話,那麼最好將事務隔離級別設定為SERIALIZABLE。 地球人都知道,SERIALIZABLE(序列化)是四個事務隔離級別中最高的一個級別,也是執行效率最低的一個級別。

2、單點故障。由於協調者的重要性,一旦協調者TM發生故障。參與者RM會一直阻塞下去。尤其在第二階段,協調者發生故障,那麼所有的參與者還都處於鎖定事務資源的狀態中,而無法繼續完成事務操作。(如果是協調者掛掉,可以重新選舉一個協調者,但是無法解決因為協調者當機導致的參與者處於阻塞狀態的問題)

3、資料不一致。在二階段提交的階段二中,當協調者向參與者傳送commit請求之後,發生了區域性網路異常或者在傳送commit請求過程中協調者發生了故障,這回導致只有一部分參與者接受到了commit請求。而在這部分參與者接到commit請求之後就會執行commit操作。但是其他部分未接到commit請求的機器則無法執行事務提交。於是整個分散式系統便出現了資料不一致性的現象。

由於二階段提交存在著諸如同步阻塞、單點問題等缺陷,所以,研究者們在二階段提交的基礎上做了改進,提出了三階段提交。

5 三階段提交協議(Three-phase commit)

三階段提交(3PC),是二階段提交(2PC)的改進版本。參考維基百科:https://en.wikipedia.org/wiki/Three-phase_commit_protocol

與兩階段提交不同的是,三階段提交有兩個改動點。

1、引入超時機制。同時在協調者和參與者中都引入超時機制。

2、在第一階段和第二階段中插入一個準備階段。保證了在最後提交階段之前各參與節點的狀態是一致的。也就是說,除了引入超時機制之外,3PC把2PC的準備階段再次一分為二,這樣三階段提交就有CanCommit、PreCommit、DoCommit三個階段。

file

CanCommit階段

3PC的CanCommit階段其實和2PC的準備階段很像。協調者向參與者傳送commit請求,參與者如果可以提交就返回Yes響應,否則返回No響應。

1.事務詢問 協調者向參與者傳送CanCommit請求。詢問是否可以執行事務提交操作。然後開始等待參與者的響應。

2.響應反饋 參與者接到CanCommit請求之後,正常情況下,如果其自身認為可以順利執行事務,則返回Yes響應,並進入預備狀態。否則反饋No

PreCommit階段

協調者根據參與者的反應情況來決定是否可以記性事務的PreCommit操作。根據響應情況,有以下兩種可能。

假如協調者從所有的參與者獲得的反饋都是Yes響應,那麼就會執行事務的預執行。

1.傳送預提交請求 協調者向參與者傳送PreCommit請求,並進入Prepared階段。    

2.事務預提交 參與者接收到PreCommit請求後,會執行事務操作,並將undo和redo資訊記錄到事務日誌中。

3.響應反饋 如果參與者成功的執行了事務操作,則返回ACK響應,同時開始等待最終指令。

假如有任何一個參與者向協調者傳送了No響應,或者等待超時之後,協調者都沒有接到參與者的響應,那麼就執行事務的中斷。

1.傳送中斷請求 協調者向所有參與者傳送abort請求。

2.中斷事務 參與者收到來自協調者的abort請求之後(或超時之後,仍未收到協調者的請求),執行事務的中斷。

doCommit階段

該階段進行真正的事務提交,也可以分為以下兩種情況。

Case 1:執行提交

1.傳送提交請求 協調接收到參與者傳送的ACK響應,那麼他將從預提交狀態進入到提交狀態。並向所有參與者傳送doCommit請求。

2.事務提交 參與者接收到doCommit請求之後,執行正式的事務提交。並在完成事務提交之後釋放所有事務資源。

3.響應反饋 事務提交完之後,向協調者傳送Ack響應。

4.完成事務 協調者接收到所有參與者的ack響應之後,完成事務。

Case 2:中斷事務 協調者沒有接收到參與者傳送的ACK響應(可能是接受者傳送的不是ACK響應,也可能響應超時),那麼就會執行中斷事務。

1.傳送中斷請求 協調者向所有參與者傳送abort請求

2.事務回滾 參與者接收到abort請求之後,利用其在階段二記錄的undo資訊來執行事務的回滾操作,並在完成回滾之後釋放所有的事務資源。

3.反饋結果 參與者完成事務回滾之後,向協調者傳送ACK訊息

4.中斷事務 協調者接收到參與者反饋的ACK訊息之後,執行事務的中斷。 



在doCommit階段,如果參與者無法及時接收到來自協調者的doCommit或者rebort請求時,會在等待超時之後,會繼續進行事務的提交。(其實這個應該是基於概率來決定的,當進入第三階段時,說明參與者在第二階段已經收到了PreCommit請求,那麼協調者產生PreCommit請求的前提條件是他在第二階段開始之前,收到所有參與者的CanCommit響應都是Yes。(一旦參與者收到了PreCommit,意味他知道大家其實都同意修改了)所以,一句話概括就是,當進入第三階段時,由於網路超時等原因,雖然參與者沒有收到commit或者abort響應,但是他有理由相信:成功提交的機率很大。 )

小結:2PC與3PC的區別

相對於2PC,3PC主要解決的單點故障問題,並減少阻塞,因為一旦參與者無法及時收到來自協調者的資訊之後,他會預設執行commit。而不會一直持有事務資源並處於阻塞狀態。但是這種機制也會導致資料一致性問題,因為,由於網路原因,協調者傳送的abort響應沒有及時被參與者接收到,那麼參與者在等待超時之後執行了commit操作。這樣就和其他接到abort命令並執行回滾的參與者之間存在資料不一致的情況。

瞭解了2PC和3PC之後,我們可以發現,無論是二階段提交還是三階段提交都無法徹底解決分散式的一致性問題。Google Chubby的作者Mike Burrows說過, there is only one consensus protocol, and that’s Paxos” – all other approaches are just broken versions of Paxos. 意即世上只有一種一致性演算法,那就是Paxos,所有其他一致性演算法都是Paxos演算法的不完整版。後面的文章會介紹這個公認為難於理解但是行之有效的Paxos演算法。   

6 BASE理論與柔性事務

6.1 經典的分散式系統理論-CAP

2000年7月,加州大學伯克利分校的Eric Brewer教授在ACM PODC會議上提出CAP猜想。Brewer認為在設計一個大規模的分散式系統時會遇到三個特性:一致性(consistency)、可用性(Availability)、分割槽容錯(partition-tolerance),而一個分散式系統最多隻能滿足其中的2項。2年後,麻省理工學院的Seth Gilbert和Nancy Lynch從理論上證明了CAP。之後,CAP理論正式成為分散式計算領域的公認定理。 

file

  1. 一致性

    一致性指“all nodes see the same data at the same time”,即更新操作成功並返回客戶端完成後,所有節點在同一時間的資料完全一致,不能存在中間狀態。例如對於電商系統使用者下單操作,庫存減少、使用者資金賬戶扣減、積分增加等操作必須在使用者下單操作完成後必須是一致的。不能出現類似於庫存已經減少,而使用者資金賬戶尚未扣減,積分也未增加的情況。如果出現了這種情況,那麼就認為是不一致的。

    關於一致性,如果的確能像上面描述的那樣時刻保證客戶端看到的資料都是一致的,那麼稱之為強一致性。如果允許存在中間狀態,只要求經過一段時間後,資料最終是一致的,則稱之為最終一致性。此外,如果允許存在部分資料不一致,那麼就稱之為弱一致性。

  2. 可用性

    可用性是指系統提供的服務必須一直處於可用的狀態,對於使用者的每一個操作請求總是能夠在有限的時間內返回結果。“有限的時間內”是指,對於使用者的一個操作請求,系統必須能夠在指定的時間內返回對應的處理結果,如果超過了這個時間範圍,那麼系統就被認為是不可用的。試想,如果一個下單操作,為了保證分散式事務的一致性,需要10分鐘才能處理完,那麼使用者顯然是無法忍受的。“返回結果”是可用性的另一個非常重要的指標,它要求系統在完成對使用者請求的處理後,返回一個正常的響應結果,不論這個結果是成功還是失敗。

  3. 分割槽容錯性

    分散式系統在遇到任何網路分割槽故障的時候,仍然需要能夠保證對外提供滿足一致性和可用性的服務,除非是整個網路環境都發生了故障。

小結: 既然一個分散式系統無法同時滿足一致性、可用性、分割槽容錯性三個特點,我們就需要拋棄一個,需要明確的一點是,對於一個分散式系統而言,分割槽容錯性是一個最基本的要求。因為既然是一個分散式系統,那麼分散式系統中的元件必然需要被部署到不同的節點,否則也就無所謂分散式系統了。而對於分散式系統而言,網路問題又是一個必定會出現的異常情況,因此分割槽容錯性也就成為了一個分散式系統必然需要面對和解決的問題。因此係統架構師往往需要把精力花在如何根據業務特點在C(一致性)和A(可用性)之間尋求平衡。而前面我們提到的X/Open XA 兩階段提交協議的分散式事務方案,強調的就是一致性;由於可用性較低,實際應用的並不多。而基於BASE理論的柔性事務,強調的是可用性,目前大行其道,大部分網際網路公司採可能會優先採用這種方案。

6.2 BASE理論

eBay的架構師Dan Pritchett源於對大規模分散式系統的實踐總結,在ACM上發表文章提出BASE理論。文章連結:https://queue.acm.org/detail.cfm?id=1394128

BASE理論是對CAP理論的延伸,核心思想是即使無法做到強一致性(Strong Consistency,CAP的一致性就是強一致性),但應用可以採用適合的方式達到最終一致性(Eventual Consitency)。    

BASE是Basically Available(基本可用)、Soft state(軟狀態)和Eventually consistent(最終一致性)三個短語的縮寫。

1. 基本可用(Basically Available)

    指分散式系統在出現不可預知故障的時候,允許損失部分可用性。

2. 軟狀態( Soft State)

    指允許系統中的資料存在中間狀態,並認為該中間狀態的存在不會影響系統的整體可用性。

3. 最終一致( Eventual Consistency)

    強調的是所有的資料更新操作,在經過一段時間的同步之後,最終都能夠達到一個一致的狀態。因此,最終一致性的本質是需要系統保證最終資料能夠達到一致,而不需要實時保證系統資料的強一致性。

BASE理論面向的是大型高可用可擴充套件的分散式系統,和傳統的事物ACID特性是相反的。它完全不同於ACID的強一致性模型,而是通過犧牲強一致性來獲得可用性,並允許資料在一段時間內是不一致的,但最終達到一致狀態。但同時,在實際的分散式場景中,不同業務單元和元件對資料一致性的要求是不同的,因此在具體的分散式系統架構設計過程中,ACID特性和BASE理論往往又會結合在一起。

6.3 典型的柔性事務方案

 最大努力通知(非可靠訊息、定期校對)

 可靠訊息最終一致性(非同步確保型)

 TCC(兩階段型、補償型)

來源:http://www.tianshouzhi.com/api/tutorials/distributed_transaction

歡迎關注公眾號 【碼農開花】一起學習成長 我會一直分享Java乾貨,也會分享免費的學習資料課程和麵試寶典 回覆:【計算機】【設計模式】【面試】有驚喜哦

相關文章