使用MQ來保證分佈式事務的最終一致性

前言

以前咱們討論瞭如何拆分一個訂單下單的一個服務(https://www.cnblogs.com/linkstar/p/9610268.html)
從單體到微服務的拆分,當時咱們只是對原來的整個服務作了一個簡單的拆分,可是在實際中確定會遇到不少問題,因此咱們這裏解決一個最容易也是最有可能在實際中遇到的問題,事務。html

在單體架構中,咱們很容易去維護一個事務,咱們想要對一個事務操做回滾也很容易,而在分離成微服務以後,咱們想要在多個服務上去維護一個事務就比較困難了。這裏咱們再也不討論分步事務的實現,轉而討論一個咱們經常聽到的,最終一致性。git

簡單的說,不少在實際中的應用多數狀況下,想要保證的是隻要最後的最結果是對的,中間的過程可能幾經周折都沒有關係。github

咱們繼續拿下單這個例子,想要保證的是,只要最後錢扣了,訂單生產了,就對了。假設其中的一個服務掛了,可能通過不斷的重試,最終等服務正常以後,結果仍是對了,也就滿意。針對這樣的狀況,咱們稱爲「最終一致性」。(這裏對於它再也不過多解釋)segmentfault

使用MQ的緣由

那麼針對最終一致性爲何要使用mq呢?我想不少人也知道網上不少人在說mq實現最終一致性,可是歷來沒有仔細想一想爲何要用mq。我列出這幾個緣由來供你參考:
一、mq能夠解決http請求出現異常的時候帶來的一系列問題
二、mq能夠有多個消費者,徹底契合微服務
三、mq本質是隊列,在高併發下,能夠保證你的數據正常
...架構

邏輯流程圖

併發

生產者的邏輯
一、訂單入庫
二、消息記錄入庫
三、發送消息(採用確認模式)
四、mq收到消息以後給生產端一個確認消息
五、生產端監聽這個確認消息
六、根據監聽結果操做消息表的狀態
七、定時任務定時去操做消息狀態爲1未發送的記錄,就是那些沒有監聽到結果的記錄進行從新發送分佈式

消費者的邏輯
一、將收到消息的消息入庫
二、處理消息失敗消息記錄的狀態就爲未處理
三、處理消息成功修改消息記錄的狀態爲處理成功
四、收到相同的消息id的消息直接丟棄
五、定時任務去操做那些未處理,而且已經通過一段時間的消息
六、針對那些一直處理失敗的,且很長一段時間都沒辦法處理成功的消息交由人工或者其餘途徑處理微服務

須要注意的問題

一、消息的100%投遞
首先咱們須要保證的就是消息必定要投遞出去,要是咱們消息都不能保證投遞成功,那麼後面的邏輯就走不下去了。高併發

二、咱們須要保證冪等性(不管多少次操做,最後形成的結果和只執行一次形成的結果是同樣的。)
消息確定會出現重複投遞的問題,這裏應該由消費端去保證,重複的消息不能進行消費htm

而保證這兩個問題的方式就藏在上面的邏輯流程圖中,請仔細揣摩其中的用意。

代碼實現

https://github.com/LinkinStars/MicroServiceExample/tree/distributed-transaction

參考博客

http://www.javashuo.com/article/p-wesansdp-s.html

具體其餘細節這裏講的很清楚,這裏再也不贅述,針對分佈式事務,一直都是一個難題,當前的解決方案有不少,適應不一樣的應用場景,因此須要根據實際項目使用場景來選取。

相關文章
相關標籤/搜索