分散式學習筆記八:漫畫什麼是分散式事務?
版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/bjweimengshu/article/details/79607522
點選上方“程式設計師小灰”,選擇“置頂公眾號”
不知道你是否遇到過這樣的情況,去小賣鋪買東西,付了錢,但是店主因為處理了一些其他事,居然忘記你付了錢,又叫你重新付。又或者在網上購物明明已經扣款,但是卻告訴我沒有發生交易。這一系列情況都是因為沒有事務導致的。這說明了事務在生活中的一些重要性。有了事務,你去小賣鋪買東西,那就是一手交錢一手交貨。有了事務,你去網上購物,扣款即產生訂單交易。
事務提供一種機制將一個活動涉及的所有操作納入到一個不可分割的執行單元,組成事務的所有操作只有在所有操作均能正常執行的情況下方能提交,只要其中任一操作執行失敗,都將導致整個事務的回滾。
簡單地說,事務提供一種“要麼什麼都不做,要麼做全套(All or Nothing)”機制。
說到資料庫事務就不得不說,資料庫事務中的四大特性 ACID:
A:原子性(Atomicity),一個事務(transaction)中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。
事務在執行過程中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。
就像你買東西要麼交錢收貨一起都執行,要麼發不出貨,就退錢。
C:一致性(Consistency),事務的一致性指的是在一個事務執行之前和執行之後資料庫都必須處於一致性狀態。
如果事務成功地完成,那麼系統中所有變化將正確地應用,系統處於有效狀態。
如果在事務中出現錯誤,那麼系統中的所有變化將自動地回滾,系統返回到原始狀態。
I:隔離性(Isolation),指的是在併發環境中,當不同的事務同時操縱相同的資料時,每個事務都有各自的完整資料空間。
由併發事務所做的修改必須與任何其他併發事務所做的修改隔離。事務檢視資料更新時,資料所處的狀態要麼是另一事務修改它之前的狀態,要麼是另一事務修改它之後的狀態,事務不會檢視到中間狀態的資料。
打個比方,你買東西這個事情,是不影響其他人的。
D:永續性(Durability),指的是隻要事務成功結束,它對資料庫所做的更新就必須永久儲存下來。
即使發生系統崩潰,重新啟動資料庫系統後,資料庫還能恢復到事務成功結束時的狀態。
打個比方,你買東西的時候需要記錄在賬本上,即使老闆忘記了那也有據可查。
InnoDB 是 MySQL 的一個儲存引擎,大部分人對 MySQL 都比較熟悉,這裡簡單介紹一下資料庫事務實現的一些基本原理。
在本地事務中,服務和資源在事務的包裹下可以看做是一體的,如下圖:
我們的本地事務由資源管理器進行管理:
而事務的 ACID 是通過 InnoDB 日誌和鎖來保證。事務的隔離性是通過資料庫鎖的機制實現的,永續性通過 Redo Log(重做日誌)來實現,原子性和一致性通過 Undo Log 來實現。
Undo Log 的原理很簡單,為了滿足事務的原子性,在操作任何資料之前,首先將資料備份到一個地方(這個儲存資料備份的地方稱為 Undo Log)。然後進行資料的修改。
如果出現了錯誤或者使用者執行了 Rollback 語句,系統可以利用 Undo Log 中的備份將資料恢復到事務開始之前的狀態。
和 Undo Log 相反,Redo Log 記錄的是新資料的備份。在事務提交前,只要將 Redo Log 持久化即可,不需要將資料持久化。
當系統崩潰時,雖然資料沒有持久化,但是 Redo Log 已經持久化。系統可以根據 Redo Log 的內容,將所有資料恢復到最新的狀態。對具體實現過程有興趣的同學可以去自行搜尋擴充套件。
分散式事務指事務的參與者、支援事務的伺服器、資源伺服器以及事務管理器分別位於不同的分散式系統的不同節點之上。
簡單的說,就是一次大的操作由不同的小操作組成,這些小的操作分佈在不同的伺服器上,且屬於不同的應用,分散式事務需要保證這些小操作要麼全部成功,要麼全部失敗。
本質上來說,分散式事務就是為了保證不同資料庫的資料一致性。
從上面本地事務來看,我們可以分為兩塊:
Service 多個節點
Service 產生多個節點
Resource 產生多個節點
隨著網際網路快速發展,微服務,SOA 等服務架構模式正在被大規模的使用。
舉個簡單的例子,一個公司之內,使用者的資產可能分為好多個部分,比如餘額,積分,優惠券等等。
在公司內部有可能積分功能由一個微服務團隊維護,優惠券又是另外的團隊維護。
這樣的話就無法保證積分扣減了之後,優惠券能否扣減成功。
Resource多個節點
同樣的,網際網路發展得太快了,我們的 MySQL 一般來說裝千萬級的資料就得進行分庫分表。
對於一個支付寶的轉賬業務來說,你給朋友轉錢,有可能你的資料庫是在北京,而你的朋友的錢是存在上海,所以我們依然無法保證他們能同時成功。
分散式事務的基礎
從上面來看分散式事務是隨著網際網路高速發展應運而生的,這是一個必然。
我們之前說過資料庫的 ACID 四大特性,已經無法滿足我們分散式事務,這個時候又有一些新的大佬提出一些新的理論。
CAP 定理,又被叫作布魯爾定理。對於設計分散式系統(不僅僅是分散式事務)的架構師來說,CAP 就是你的入門理論。
C (一致性):對某個指定的客戶端來說,讀操作能返回最新的寫操作。
對於資料分佈在不同節點上的資料來說,如果在某個節點更新了資料,那麼在其他節點如果都能讀取到這個最新的資料,那麼就稱為強一致,如果有某個節點沒有讀取到,那就是分散式不一致。
A (可用性):非故障的節點在合理的時間內返回合理的響應(不是錯誤和超時的響應)。可用性的兩個關鍵一個是合理的時間,一個是合理的響應。
合理的時間指的是請求不能無限被阻塞,應該在合理的時間給出返回。合理的響應指的是系統應該明確返回結果並且結果是正確的,這裡的正確指的是比如應該返回 50,而不是返回 40。
P (分割槽容錯性):當出現網路分割槽後,系統能夠繼續工作。打個比方,這裡叢集有多臺機器,有臺機器網路出現了問題,但是這個叢集仍然可以正常工作。
熟悉 CAP 的人都知道,三者不能共有,如果感興趣可以搜尋 CAP 的證明,在分散式系統中,網路無法 100% 可靠,分割槽其實是一個必然現象。
如果我們選擇了 CA 而放棄了 P,那麼當發生分割槽現象時,為了保證一致性,這個時候必須拒絕請求,但是 A 又不允許,所以分散式系統理論上不可能選擇 CA 架構,只能選擇 CP 或者 AP 架構。
對於 CP 來說,放棄可用性,追求一致性和分割槽容錯性,我們的 ZooKeeper 其實就是追求的強一致。
對於 AP 來說,放棄一致性(這裡說的一致性是強一致性),追求分割槽容錯性和可用性,這是很多分散式系統設計時的選擇,後面的 BASE 也是根據 AP 來擴充套件。
順便一提,CAP 理論中是忽略網路延遲,也就是當事務提交時,從節點 A 複製到節點 B 沒有延遲,但是在現實中這個是明顯不可能的,所以總會有一定的時間是不一致。
同時 CAP 中選擇兩個,比如你選擇了 CP,並不是叫你放棄 A。因為 P 出現的概率實在是太小了,大部分的時間你仍然需要保證 CA。
就算分割槽出現了你也要為後來的 A 做準備,比如通過一些日誌的手段,是其他機器回覆至可用。
BASE 是 Basically Available(基本可用)、Soft state(軟狀態)和 Eventually consistent (最終一致性)三個短語的縮寫,是對 CAP 中 AP 的一個擴充套件。
基本可用:分散式系統在出現故障時,允許損失部分可用功能,保證核心功能可用。
軟狀態:允許系統中存在中間狀態,這個狀態不影響系統可用性,這裡指的是 CAP 中的不一致。
最終一致:最終一致是指經過一段時間後,所有節點資料都將會達到一致。
BASE 解決了 CAP 中理論沒有網路延遲,在 BASE 中用軟狀態和最終一致,保證了延遲後的一致性。
BASE 和 ACID 是相反的,它完全不同於 ACID 的強一致性模型,而是通過犧牲強一致性來獲得可用性,並允許資料在一段時間內是不一致的,但最終達到一致狀態。
假如沒有分散式事務
在一系列微服務系統當中,假如不存在分散式事務,會發生什麼呢?讓我們以網際網路中常用的交易業務為例子:
上圖中包含了庫存和訂單兩個獨立的微服務,每個微服務維護了自己的資料庫。在交易系統的業務邏輯中,一個商品在下單之前需要先呼叫庫存服務,進行扣除庫存,再呼叫訂單服務,建立訂單記錄。
正常情況下,兩個資料庫各自更新成功,兩邊資料維持著一致性。
但是,在非正常情況下,有可能庫存的扣減完成了,隨後的訂單記錄卻因為某些原因插入失敗。這個時候,兩邊資料就失去了應有的一致性。
什麼是分散式事務?
分散式事務用於在分散式系統中保證不同節點之間的資料一致性。分散式事務的實現有很多種,最具有代表性的是由Oracle Tuxedo系統提出的XA分散式事務協議。
XA協議包含兩階段提交(2PC)和三階段提交(3PC)兩種實現,這裡我們重點介紹兩階段提交的具體過程。
在魔獸世界這款遊戲中,副本組團打BOSS的時候,為了更方便隊長與隊員們之間的協作,隊長可以發起一個“就位確認”的操作:
當隊員收到就位確認提示後,如果已經就位,就選擇“是”,如果還沒就位,就選擇“否”。
當隊長收到了所有人的就位確認,就會向所有隊員們釋出訊息,告訴他們開始打BOSS。
相應的,在隊長髮起就位確認的時候,有可能某些隊員還並沒有就位:
以上就是魔獸世界當中組團打BOSS的確認流程。這個流程和XA分散式事務協議的兩階段提交非常相似。
那麼XA協議究竟是什麼樣子呢?在XA協議中包含著兩個角色:事務協調者和事務參與者。讓我們來看一看他們之間的互動流程:
第一階段:
在XA分散式事務的第一階段,作為事務協調者的節點會首先向所有的參與者節點發送Prepare請求。
在接到Prepare請求之後,每一個參與者節點會各自執行與事務有關的資料更新,寫入Undo Log和Redo Log。如果參與者執行成功,暫時不提交事務,而是向事務協調節點返回“完成”訊息。
當事務協調者接到了所有參與者的返回訊息,整個分散式事務將會進入第二階段。
第二階段:
在XA分散式事務的第二階段,如果事務協調節點在之前所收到都是正向返回,那麼它將會向所有事務參與者發出Commit請求。
接到Commit請求之後,事務參與者節點會各自進行本地的事務提交,並釋放鎖資源。當本地事務完成提交後,將會向事務協調者返回“完成”訊息。
當事務協調者接收到所有事務參與者的“完成”反饋,整個分散式事務完成。
以上所描述的是XA兩階段提交的正向流程,接下來我們看一看失敗情況的處理流程:
第一階段:
第二階段:
在XA的第一階段,如果某個事務參與者反饋失敗訊息,說明該節點的本地事務執行不成功,必須回滾。
於是在第二階段,事務協調節點向所有的事務參與者傳送Abort請求。接收到Abort請求之後,各個事務參與者節點需要在本地進行事務的回滾操作,回滾操作依照Undo Log來進行。
以上就是XA兩階段提交協議的詳細過程。
XA兩階段提交的不足
XA兩階段提交究竟有哪些不足呢?
1.效能問題
XA協議遵循強一致性。在事務執行過程中,各個節點佔用著資料庫資源,只有當所有節點準備完畢,事務協調者才會通知提交,參與者提交後釋放資源。這樣的過程有著非常明顯的效能問題。
2.協調者單點故障問題
事務協調者是整個XA模型的核心,一旦事務協調者節點掛掉,參與者收不到提交或是回滾通知,參與者會一直處於中間狀態無法完成事務。
3.丟失訊息導致的不一致問題。
在XA協議的第二個階段,如果發生區域性網路問題,一部分事務參與者收到了提交訊息,另一部分事務參與者沒收到提交訊息,那麼就導致了節點之間資料的不一致。
如果避免XA兩階段提交的種種問題呢?有許多其他的分散式事務方案可供選擇:
1.XA三階段提交
XA三階段提交在兩階段提交的基礎上增加了CanCommit階段,並且引入了超時機制。一旦事物參與者遲遲沒有接到協調者的commit請求,會自動進行本地commit。這樣有效解決了協調者單點故障的問題。但是效能問題和不一致的問題仍然沒有根本解決。
2.MQ事務
利用訊息中介軟體來非同步完成事務的後一半更新,實現系統的最終一致性。這個方式避免了像XA協議那樣的效能問題。
3.TCC事務
TCC事務是Try、Commit、Cancel三種指令的縮寫,其邏輯模式類似於XA兩階段提交,但是實現方式是在程式碼層面來人為實現。
---------------------
作者:玻璃貓
來源:CSDN
原文:https://blog.csdn.net/bjweimengshu/article/details/79607522
版權宣告:本文為博主原創文章,轉載請附上博文連結!