消息服務框架(MSF)應用實例之分散式事務三階段提交協議的實現

来源:https://www.cnblogs.com/bluedoctor/archive/2017/12/29/8146604.html
-Advertisement-
Play Games

分散式事務常常使用2階段提交或者3階段提交,那麼這兩種方式的區別是什麼?3階段提交協議是不是就完美了?圖文解釋,簡單易懂。 ...


一,分散式事務簡介

在當前互聯網,大數據和人工智慧的熱潮中,傳統企業也受到這一潮流的衝擊,紛紛響應國家“互聯網+”的戰略號召,企業開始將越來越多的應用從公司內網遷移到雲端和移動端,或者將之前孤立的IT系統聯網整合,或者將原來厚重的企業應用拆分重組,獨立成一個個輕量級的應用對外提供服務,這對傳統的業務處理的數據一致性,帶來了嚴重的挑戰,我們已經身處一個分散式的計算環境,分散式事務的需求越來越普遍。

舉一個例子,某行業電商網站經過幾年的發展,業務數據累積越來越多,查詢越來越慢。經過內部評審分析,認為系統的瓶頸就是資料庫壓力過大,如果要解決這問題,必須分表分庫,比如將訂單,商品,用戶分佈到不同的資料庫去,但這樣隨之帶來一個問題,原來處理業務的時候使用的是本地事務,分庫後就需要使用分散式事務了。

那麼應該如何實現分散式事務呢?

這裡我們需要明確一點,並非資料庫天然就是分散式的在執行操作的,事務都是在一個資料庫實例上進行的,如果要執行一個分散式事務的操作,那麼就需要協調多個分散的資料庫上執行的事務操作。所以在分散式事務中,有2個概念:

l  Distributed Transaction Resource Owner (簡稱DTR):

n  --分散式事務資源伺服器,擁有事務資源的伺服器,如絕大部分關係資料庫,一些消息隊列,或者一些能夠執行類似事務操作的應用。

l  Distributed Transaction Coordinate Controller (簡稱DTC):

n  --分散式事務協調控制器,它協調控制分散式事務環境中的事務資源伺服器,發送指令給它們並且處理事務資源伺服器返回的結果。

 

二,分散式事務的實現層面

 

在分散式事務的具體實現層面,可以在資料庫層直接實現,也可以在應用服務層面實現。如果是在應用服務層面實現,本質上它也可能是調用本地的資料庫事務。

下麵是DTR與DTC的拓撲關係圖:

基於關係資料庫層面介面實現的分散式事務

基於資料庫的分散式事務,一般在應用程式的數據層調用系統的分散式事務組件,應用程式執行本地事務的時候,先選舉出一個分散式事務協調器,然後協調器來協調各個本地事務的執行。由於是在應用程式的數據層進行的調用,所以它對遠程資料庫的操作是在本地進程內的。如果你的應用部署在多台伺服器上,那麼在每一臺操作資料庫的應用伺服器上都要安裝運行分散式事務協調器服務。

基於應用服務層面實現的分散式事務

 

基於應用服務層面的分散式事務,是在應用服務層面進行的事務控制,它同樣會有分散式事務協調控制器,和事務資源伺服器。與基於資料庫層面的分散式事務不同,事務的類型支持更廣泛,比如消息隊列訪問,文件寫入或者具有補償操作的業務應用程式,都可以成為事務資源,並且不要求這些事務資源本身支持分散式事務。舉個例子,事務資源A是Windows上的SQLSERVER資料庫,事務B是Linux上的MySQL資料庫,這時候事務B就沒法使用Windows上的事務協調控制器MSDTC了。而基於服務層面的分散式事務,可以解決這個問題。

三,分散式事務的2階段提交協議(2PC)

第一階段(1PC):提交投票階段

協調器向事務資源伺服器發出 CanCommit 的是否可以提交事務的詢問指令,事務資源伺服器收到此指令後,準備好要提交的事務資源,再向協調器回覆 YES;如果沒有準備好,比如執行事務中的操作出現了錯誤,應該回覆 NO.如果某DTR無法回覆,DTC也認為該DTR的結果是NO.

第一階段,全部回覆為YES,代表各個事務資源伺服器均已經準備好了提交。

 

第一階段,事務資源伺服器DTR-2回覆為NO,如果DTC等待DTR-2超過設定時間都沒有得到回覆,或者DTR-2與DTC斷開了連接,也認為DTR-2的結果是NO

 

第二階段(2 PC):提交或終止階段

協調器統計所有事物資源伺服器的回覆數量,如果全部回覆為YES,則向所有事物資源伺服器發出Commit指令,否則,發出Abort指令。資源伺服器收到指令後,執行相應的操作。

二階段提交事務的數據不一致問題

在第二階段(2PC),如果DTR沒有收到DTC的指令改怎麼辦呢?

如果等到超時都沒有收到DTC的指令,DTR處於“可以提交”或者“不可以提交”的雙重狀態,也就是提交狀態不可知。假設DTR1沒有收到DTC的提交指令或者撤銷指令,DTR1可以假設DTR2也不會收到指令,因為此時大概率是DTC宕機或者網路整體不良,那麼DTR1最佳的做法是回滾事務。

但是,如果僅僅是DTR1受網路影響沒有收到提交指令,而DTR2收到了提交指令,那麼DTR1回滾事務,DTR2提交了事務,整個分散式事務就是失敗的,數據發生了不一致。

因此,2階段提交的分散式事務不是高可靠的分散式事務控制模型,需要在事務資源的提交環節做更多的驗證,這便是3階段提交的分散式事務。

 

不過,對於大部分系統,2階段提交的分散式事務已經能夠滿足應用了,因為通常情況下,都是基於資料庫應用層實現的分散式事務,並且各個事務資源節點都在同一個區域網內,發生網路不穩定的概率非常小,並且現在不少資料庫都會做高可靠性的資料庫集群,發生宕機的可能性也非常小,最終出現數據不一致的概率也就非常小了。

 

如果系統的應用環境不能滿足上面說的任何一個條件,即分散式事務的控制不是在資料庫應用層,子系統不在一個區域網,或者資料庫沒有做高可靠的集群,並且對於系統的事務一致性要求非常高,那麼應該使用3階段提交協議來實現分散式事務。

四,分散式事務的3階段提交協議(3PC)

對2階段提交協議的分析我們發現,2PC的事務提交階段狀態是不確定的,整個事務容易出現不一致的情況。所以,我們隊2PC的提交階段,進一步拆分成“預提交”階段和提交階段,增加事務提交狀態的確認過程。

第一階段(1PC):提交投票階段

協調器向事務資源伺服器發出 CanCommit 的是否可以提交事務的詢問指令,事務資源伺服器收到此指令後,準備好要提交的事務資源,再向協調器回覆 YES;如果沒有準備好,比如執行事務中的操作出現了錯誤,應該回覆 NO.如果某DTR無法回覆,DTC也認為該DTR的結果是NO.

該階段的處理過程跟2階段提交協議的第一階段是一樣的,處理流程圖參考前面,此略。

 

第二階段(2 PC):預提交或終止階段

預提交事務

協調器(DTC)統計所有事務資源伺服器(DTR)的回覆數量,如果全部回覆為YES,則向所有事物資源伺服器發出PreCommit指令,否則,發出Abort指令。資源伺服器收到指令後,執行相應的操作。

在第二階段,如果DTR收到PreCommit指令,則向DTC回覆ACK消息,表示收到了指令,準備提交,接著,進入第三階段,等待最終的提交指令。

 

終止事務

在第二階段,如果在第一階段有節點異常,DTC發出撤銷指令,DTR收到了撤銷指令,那麼它執行回滾本地事務的操作。如果由於網路原因,某個DTR一直等到超時都沒有收到PreCommit指令,那麼它執行Abort撤銷指令,回滾本地事務。

 

第三階段(3 PC):提交或終止階段

提交分散式事務

協調器(DTC)統計所有事務資源伺服器(DTR)在第二階段的回覆數量,如果全部回覆為ACK,則向所有DTR發出Commit指令。DTR收到指令後,執行事務提交操作,並返回Commit Done消息,DTC收到此消息,結束整個分散式事務過程。

 

 

回滾分散式事務

協調器(DTC)統計所有事務資源伺服器(DTR)在第二階段的回覆數量,如果未收到全部回覆為ACK,則它認為有節點可能出現了網路故障,此節點沒有收到PreCommit指令或者雖然收到了卻沒有回覆ACK,測試DTC應該向所有DTR節點發出撤銷指令。各DTR收到撤銷指令後,回滾本地事務,然後回覆消息,DTC完成本次事務過程。

 

三階段提交事務也並不完美

考察第3階段的提交分散式事務的情況,DTR1收到了Commit指令,但是由於網路原因,DTR2沒有收到此指令,那麼DTR2是提交本地事務還是回滾本地事務?

站在DTR2的角度,它在本階段可能收到Commit指令,也可能收到Abort指令,那麼它既可以提交本地事務也可以回滾本地事務,兩種操作是不確定的,所以,3階段提交協議,仍然不是完美的,不能百分之百保證數據的最終一致性。

既然3階段提交協議仍然有不確定性,那麼相比2階段提交協議有什麼意義呢?

 

仔細想下,DTR2已經進入第3階段了,那麼肯定其它DTR都進入了第3階段,而進入第3階段的前提是各DTR節點都收到過PreCommit指令,都是已經準備好提交只等最後的提交指令了,否則各節點在第二階段應該收到撤銷指令,不會再進入第三階段。既然各DTR節點都進入了第三階段,它們都準備好提交事務了,那麼即使沒有收到最終的Commit指令,DTC發出Commit指令也是大概率的。所以,從概率上講,如果在第三階段,DTR沒有收到Abort撤銷指令,也沒收到Commit提交指令,那麼它預設應該指向Commit指令,提交本地事務。相比第二階段某DTR節點沒有收到指令而認為應該收到PreCommit指令的概率,要大得多。

 

關於第三階段沒有收到指令而應該大概率執行Commit指令的問題,理解起來可能有點困難,我給同事講的時候大部分同事也難以理解,可能是我表述的問題,大家有更好的解釋方式,歡迎交流,不勝感激!

 

5,實現 3階段提交的分散式事務

本文將介紹一個基於服務層面而不是資料庫層面的,3階段提交的分散式事務中間件的設計開發過程。這個中間件必須解決下麵幾個問題:

l  通信組件—分散式事務控制器(DTC),分散式事務資源伺服器(DTR)都是獨立的服務,這些服務部署在不同的通信節點,它們之間需要進行可靠的網路通信,因此通信組件是基礎;

l  數據訪問組件—提供基礎的數據讀寫操作,並且能夠操作本地事務。

l  服務組件—將DTC,DTR的功能代碼編寫為相應的SOA服務組件

l  關係資料庫—具有事務功能的關係資料庫,可以是嵌入式的本地資料庫,比如SQLite,也可以是伺服器客戶機模式的網路資料庫,比如SQLSERVER。

 

各組件的關係圖如下:

 

PDF.NET的消息服務框架(MSF)具有開發服務組件基礎的介面和一套消息通信組件,同時還有一個服務容器,可以承載本篇文章說的分散式事務控制器DTC,分散式事務資源服務DTR這些服務應用,同時PDF.NET還有一個強大的數據訪問組件 PDF.NET SOD,下一篇文章,我們將來具體討論基於MSF和SOD的3階段分散式事務應用的實現過程,它的源碼已經發佈在 https://github.com/bluedoctor/MSF-DistTransExample ,大家可以先睹為快。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • AOP的概念,使用過Spring的人應該都不陌生了。Dojo中,也是支持AOP的。對於JavaScript的其他框架、庫不知道有沒有AOP的支持。相信即便沒有支持,也不會太遠了。下麵就介紹一下使用JavaScript實現AOP。 AOP的思想就是在目標方法前後加入代碼: var result=nul ...
  • 相容性 相容性:瀏覽器相容問題和適配問題統稱為相容性問題 解決辦法 1.hack語法,控制解決辦法 <!--[if <keywords>? IE <version>?]> HTML代碼塊 <![endif]--> eg:<!--[if gt IE 6]> ...... <![endif]--> 說明 ...
  • JS實現的4種數字千位符格式化方法 所謂的數字千分位形式,即從個位數起,每三位之間加一個逗號。例如“10,000”。針對這個需求,我起初寫了這樣一個函數: // 方法一 function toThousands(num) { var result = [ ], counter = 0; num = ...
  • 呃,終於到了這地方…… MMP,有31個函數,估計可以寫到明年了。 這裡先梳理所有事件的註入來源,經檢測,全部來源於WebpackOptionsApply中,回到那個可怕的模塊,梳理後如下: 還好都集中在一個地方,這樣又可以寫流水賬了。 這裡先要過一個地方,之前似乎遺留了: 這裡註入了entry-o ...
  • 在很久之前就想通過工具來規範自己的代碼風格,減少程式出錯的概率,如果看過我的 一個前端程式猿的Sublime Text3的自我修養 ,這篇博客的朋友,肯定知道在當時我使用 SublimeLinter-jshint 插件來規範風格,但是實際上一直懶癌發作也沒去看它的文檔,使用著它預設的規則。不過現在是 ...
  • 1、Vue實例常用屬性 (1)數據 data:Vue 實例的數據對象 components:Vue實例配置局部註冊組件 (2)類方法computed:計算屬性 watch:偵聽屬性 filters:過濾器 methods:Vue實例方法 render:渲染函數,創建虛擬DOM (3)生命周期crea ...
  • 1.內聯式引用:直接用在標簽上,但維護成本高 2.外部連接式引用:css代碼與html代碼分離,便於代碼重覆使用 style.css文件內容如右: 3.內部式引用:頁面較為清晰,但不能被別的頁面使用 4.外部導入式:可以在一個HTML文件中導入多個樣式表。類似於外部鏈接式引用 在HTML文件中hea ...
  • "Parcel" 是一個零配置的網路應用打包工具, 適用於經驗不同的開發者, 它利用多核處理提供了極快的速度。對比 webpack 最大的兩個亮點: 零配置 極快速 omi 相關的插件都是基於 webpack 進行開發,今天正式投入 Parcel 懷抱。 準備工作 通過 yarn 或 npm 安裝 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...