Java架構師之解決分佈式事務數據一致性開發與實踐分佈式事務實現

今天在看書的時候,看到了分佈式事務的一致性問題,就趕緊記下來。

一、分佈式事務介紹

在我們平時寫的代碼中,我們可以用一個事務包含許多個SQL調用,如果某一個數據庫操作發生異常,就可以將之前的SQL操縱全部進行回滾,只有當所以的SQL操作全部成功,才進行提交,這就保證了事務的一致性。

摳張圖看看

 

 但是在分佈式環境下,多個數據庫操作可能被拆分到獨立的三個數據庫訪問服務中,此時原來的本地SQL調用就演變成了遠程服務調用,事務的一致性無法得到保證,摳張圖來看

 

加入服務A和服務B調用成功,則A和B的SQL會被提交,最後執行服務C,它的SQL操作失敗,那麼C進行回滾,在這裏,就導致了事務的不一致。

二、分佈式事務設計方案

通常,分佈式事務基於兩階段實現,它的工作原理示意圖如下:

 

 階段1:全局事務管理器向所有事務參與者發送準備請求,事務參與者向全局事務管理器回覆自己是否準備就緒。

階段2:全局事務管理器接收到所以事務參與者的回覆之後做判斷,如果所有事務參與者都可以提交,則向所有事務提交者發送提交申請,否則進行回滾。事務參與者根據全局事務管理器的指令進行提交或者回滾操作。

分佈式事務回滾圖如下:

 

兩個階段採用的是悲觀鎖策略,由於各個事務參與者需要等待響應最慢的參與者,因此性能比較差。 而且整個過程都是需要加鎖的,並且當協調者出現故障,則整個事務需要等到協調者回復後才能繼續執行。

所以可以用最終一致性替代傳統的強一致性,儘量避免使用分佈式事務。

三、分佈式事務優化

在實踐中常用的最終一致性方案就是使用帶有事務功能的MQ做中間人角色,工作原理如下:

在做本地事務之前,先向MQ發送一個preapre消息,然後執行本地事務,本地事務提交成功的話,向MQ發送一個commit消息,否則發送一個rollback消息,取消之前的消息。MQ只會在收到commit確認纔會將消息投遞出去,所以這樣的形式可以保證在一切正常的情況下,本地事務和MQ可以達到一致性。

但是如果系統執行事務成功後,還沒來得及發送commit給MQ,或者說網絡超時等問題導致MQ沒有收到commit,那麼MQ就不會把prepare消息投遞出去。MQ會根據策略去嘗試詢問(回調)發消息的系統進行檢查該消息是否應該投遞出去或者丟棄,得到系統的確認後,MQ會做投遞還是丟棄,這樣就完全保證了MQ和發消息的系統的一致性,從而保證了接收消息系統的一致性。


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