本文內容
- 什麼是分佈式事務
- 分佈式事務中的難點
- 常見的解決方案
- 講解經過可靠消息來解決分佈式事務
什麼是分佈式事務?
有這樣一個需求:數據庫
小明有兩個帳戶,分別位於A、B兩個數據庫中,小明須要將A中的資金轉到B中。微信
咱們如何實現?網絡
按照下面的方式實現看看有沒有問題。併發
- 鏈接數據庫A,獲取connA鏈接
- connA打開事務
- A庫資金減小100
- 鏈接庫B,獲取connB鏈接
- connB打開事務
- B庫資金增長100
- connA.commit()
- connB.commit()
上面操做,正常狀況是沒有問題。異步
考慮以下狀況:分佈式
第7步執行成功以後,網絡出問題了,第8步會提交失敗,此時的結果是:A庫資金減小了100,B庫資金卻沒有增長;這是一個網絡問題致使了咱們業務失敗了,網絡因素是程序不可控的一些因素,還有其餘的好比運行到7以後,系統忽然斷電了,也會出現一樣的結果。形成了數據錯誤,對業務影響也是比較大的。微服務
分佈式事務能夠這麼理解:一個業務操做中,會包含不少子業務的,每一個子業務都是獨立的事務,咱們須要考慮的是如何保證這些子業務都成功,或者都失敗。blog
分佈式事務中的難點
- 分佈式事務中,分支多是各類各樣的,可能存在各類異常狀況致使有些成功有些卻失敗了,這些狀況須要咱們程序可以處理,保證全部的分支要麼都成功、要麼都失敗,不能出現部分紅功而部分失敗的狀況。
- 分佈式事務中,很難保證多個分支同時成功。每一個分支可能都是提供遠程接口進行調用,之間存在網絡故障的問題,前面的分支調用成功了,可是其餘分支因爲網絡等不可控的因素而調用不成功,此時數據是很難作到同時一致性的。
- 實時一致性難以保證。那麼咱們能夠作到最終一致性也是能夠的。
什麼是最終一致性?
就拿上面的轉帳來講,A庫的資金減小了,因爲網絡問題,操做B庫的connB鏈接斷開了,致使B庫資金沒有增長;網絡問題是能夠恢復了,若是網絡恢復了,系統可以給B中資金加上,這樣最終數據也是正確的;這中間有段時間AB庫的資金是不一致的(A庫減小了100,B庫應該增長100卻沒有增長,數據是不一致的),可是最終某個時間點數據變爲一致了。可以將不一致的時間降到最低是系統須要考慮的問題。接口
分佈式事務中,咱們能夠接受數據在某個時間段以內不一致,可是數據最終在某個時間點是一致的。圖片
常看法決方案
- 可靠消息模式
- TCC模式實現
分佈式事務系列中主要講這2種方案,這兩種方案基本上能夠解決大多數常見的分佈式事務的問題,因此我們必須把這兩種方式拿下。
下面咱們介紹一下使用可靠消息如何實現?
可靠消息模式實現轉帳操做

兩個微服務
服務A:用於操做A庫中的帳戶
服務B:用於操做B庫中的帳戶
兩個服務都是連接獨立的數據庫,依靠數據庫提供的功能,可以保證各自的事務。
對於用戶來講過程以下:
- 調用服務A,扣款100
- 發送扣款成功的消息到消息服務
- 返回用戶轉帳已受理
接着
- 服務B,拉取到轉帳消息
- B庫中給帳戶+100
- 調用消息服務將消息刪除
- 服務B消費的過程當中,好比出現網絡、機器重啓等緣由,致使消費失敗,等機器恢復以後,能夠再次消費這條消息,重試屢次最終會成功
上面整個轉帳過程當中有幾點咱們須要考慮一下:
- 如何確保A服務中扣款成功以後,消息必定可以發送成功;若是消息發送失敗而丟失了,後面的業務將無法進行。這塊涉及如何發送可靠消息,以前消息系列的文章有介紹,你們能夠看一下:聊聊業務系統中投遞消息到mq的幾種方式
- 咱們的服務通常都是集羣的方式,消息消費的時候,可能會出現一條消息併發消費的狀況,併發狀況發生的時候,如何確保消費只可以被消費成功一次。若是一條轉帳消息被成功消費兩次,最終B帳戶中將增長200,致使業務出錯。這塊能夠參考如何保證消息消費的冪等性,這塊以前也有講過,你們也能夠看一下:探討一下實現冪等性的幾種方式
依靠消息模式實現分佈式事物,比較適合消費者必定會處理成功的場景。好比用戶註冊發送郵件、發送短信、送積分等。
總結
- 本文主要介紹了什麼是分佈式事務、其中的一些難點
- 常見的使用最多的解決方案:異步消息處理分佈式事物、tcc模式
- tcc模式咱們在後面的文章中介紹,目前在咱們本身的系統中實現了通用的tcc,已經上線運行,運行也比較穩定
- 對分佈式事務有興趣、或有疑問的,能夠加我微信itsoku交流
能夠關注公衆號:路人甲Java,獲取年薪50萬課程,獲取最新文章。
