分佈式事務之深入理解什麼是2PC、3PC及TCC協議?

前言

在上一篇文章《教你一手如何基於RocketMQ搭建生產級消息集羣》中給大家介紹了基於RocketMQ如何搭建生產級消息集羣。因爲本系列文章最終的目的是介紹基於RocketMQ的事物消息來解決分佈式系統中的數據一致性問題,所以先給大家率先介紹了RocketMQ消息集羣的搭建。

原本是想着在這篇文章中直接介紹RocketMQ的事務消息特性,但是在梳理的過程中作者發現對於分佈式事務的概念,可能還會有很多同學不理解或者理解得不是很深刻的地方,而跳過這些基本概念直接去學習上層的實踐可能並不是一件很好的事情,因此在這篇文章中,作者打算重點給大家先介紹下分佈式事務相關的基本概念,諸如分佈式事務、2PC、3PC、TCC之類的基本問題,之後再單獨去介紹RocketMQ事務消息相關的實踐。

數據庫事務的概念

在講述分佈式事務的概念之前,我們先來回顧下事務相關的一些概念。

事務的基本概念:

就是一個程序執行單元,裏面的操作要麼全部執行成功,要麼全部執行失敗,不允許只成功一半另外一半執行失敗的事情發生。例如一段事務代碼做了兩次數據庫更新操作,那麼這兩次數據庫操作要麼全部執行成功,要麼全部回滾。

事務的基本特性

我們知道事務有4個非常重要的特性,即我們常說的(ACID)。

Atomicity(原子性):是說事務是一個不可分割的整體,所有操作要麼全做,要麼全不做;只要事務中有一個操作出錯,回滾到事務開始前的狀態的話,那麼之前已經執行的所有操作都是無效的,都應該回滾到開始前的狀態。

Consistency(一致性):是說事務執行前後,數據從一個狀態到另一個狀態必須是一致的,比如A向B轉賬( A、B的總金額就是一個一致性狀態),不可能出現A扣了錢,B卻沒收到的情況發生。

Isolation(隔離性): 多個併發事務之間相互隔離,不能互相干擾。關於事務的隔離性,可能不是特別好理解,這裏的併發事務是指兩個事務操作了同一份數據的情況;而對於併發事務操作同一份數據的隔離性問題,則是要求不能出現髒讀、幻讀的情況,即事務A不能讀取事務B還沒有提交的數據,或者在事務A讀取數據進行更新操作時,不允許事務B率先更新掉這條數據。而爲了解決這個問題,常用的手段就是加鎖了,對於數據庫來說就是通過數據庫的相關鎖機制來保證。

Durablity(持久性):事務完成後,對數據庫的更改是永久保存的,不能回滾。

關於數據庫事務的基本概念大家可以去網上搜一下,這裏只是給大家回顧下事務的基本概念及特性,諸如事務併發問題、事務隔離級別等大家如有遺忘可以去回顧下(tips:面試經常會問到的問題哦)。

什麼是分佈式事務

以上內容我們回顧了下事務的基本概念,那麼分佈式事務又是個什麼概念呢?它與數據庫事務之間又有什麼區別呢?

其實分佈式事務從實質上看與數據庫事務的概念是一致的,既然是事務也就需要滿足事務的基本特性(ACID),只是分佈式事務相對於本地事務而言其表現形式有很大的不同。舉個例子,在一個JVM進程中如果需要同時操作數據庫的多條記錄,而這些操作需要在一個事務中,那麼我們可以通過數據庫提供的事務機制(一般是數據庫鎖)來實現。

而隨着這個JVM進程(應用)被拆分成了微服務架構,原本一個本地邏輯執行單元被拆分到了多個獨立的微服務中,這些微服務又分別操作不同的數據庫和表,服務之間通過網絡調用。

舉個例子:服務A收到一筆購物下單請求後,需要調用服務B去支付,支付成功則處理購物訂單爲待發貨狀態,否則就需要將購物訂單處理爲失敗狀態。(如圖所示)

分佈式事務之深入理解什麼是2PC、3PC及TCC協議?

在上面這個例子中會不會出現服務B支付成功了,但是由於網絡調用的問題沒有通知到服務A,導致用戶付了錢,但是購物訂單無法顯示支付成功的狀態呢?

答案是這種情況是普遍存在的,因爲服務B在處理成功後需要向服務A發送網絡請求,而這個過程是極有可能失敗的。那麼如何確保“服務A->服務B”這個過程能夠組成一個事務,要麼全部成功、要麼全部失敗呢?而這就是典型的需要通過分佈式事務解決的問題。

分佈式事務是爲了解決微服務架構(形式都是分佈式系統)中不同節點之間的數據一致性問題。這個一致性問題本質上解決的也是傳統事務需要解決的問題,即一個請求在多個微服務調用鏈中,所有服務的數據處理要麼全部成功,要麼全部回滾。當然分佈式事務問題的形式可能與傳統事務會有比較大的差異,但是問題本質是一致的,都是要求解決數據的一致性問題

而分佈式事務的實現方式有很多種,最具有代表性的是由Oracle Tuxedo系統提出的XA分佈式事務協議。XA協議包括兩階段提交(2PC)三階段提交(3PC)兩種實現,接下來我們分別來介紹下這兩種實現方式的原理。

兩階段提交(2PC)

兩階段提交又稱2PC(two-phase commit protocol),2pc是一個非常經典的強一致、中心化的原子提交協議。這裏所說的中心化是指協議中有兩類節點:一個是中心化協調者節點(coordinator)和N個參與者節點(partcipant)

下面我們就以一個儘量貼近實際業務場景的操作來舉例:"假設在一個分佈式架構的系統中事務的發起者通過分佈式事務協調者(如RocketMQ,在早期RocketMQ版本不提供事務消息特性時,有些公司會自己研發一個基於MQ的可靠消息服務來實現一定的分佈式事務的特性)分別嚮應用服務A、應用服務B發起處理請求,二者在處理的過程中會分別操作自身服務的數據庫,現在要求應用服務A、應用服務B的數據處理操作要在一個事務裏"?

在上面這個例子中如果採用兩階段提交來實現分佈式事務,那麼其運行原理應該是個什麼樣的呢?(如

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章