1. 程式人生 > >使用MQ來保證分布式事務的最終一致性

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

記錄 distrib lin 項目 fault 出現 有關 targe 模式

前言

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

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

簡單的說,很多在實際中的應用多數情況下,想要保證的是只要最後的最結果是對的,中間的過程可能幾經周折都沒有關系。

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

使用MQ的原因

那麽針對最終一致性為什麽要使用mq呢?我想很多人也知道網上很多人在說mq實現最終一致性,但是從來沒有仔細想想為什麽要用mq。我列出這幾個原因來供你參考:
1、mq可以解決http請求出現異常的時候帶來的一系列問題
2、mq可以有多個消費者,完全契合微服務
3、mq本質是隊列,在高並發下,可以保證你的數據正常
...

邏輯流程圖

技術分享圖片?

生產者的邏輯
1、訂單入庫
2、消息記錄入庫
3、發送消息(采用確認模式)
4、mq收到消息之後給生產端一個確認消息
5、生產端監聽這個確認消息
6、根據監聽結果操作消息表的狀態
7、定時任務定時去操作消息狀態為1未發送的記錄,就是那些沒有監聽到結果的記錄進行重新發送

消費者的邏輯
1、將收到消息的消息入庫
2、處理消息失敗消息記錄的狀態就為未處理
3、處理消息成功修改消息記錄的狀態為處理成功
4、收到相同的消息id的消息直接丟棄
5、定時任務去操作那些未處理,並且已經經過一段時間的消息
6、針對那些一直處理失敗的,且很長一段時間都沒辦法處理成功的消息交由人工或者其他途徑處理

需要註意的問題

1、消息的100%投遞
首先我們需要保證的就是消息一定要投遞出去,要是我們消息都不能保證投遞成功,那麽後面的邏輯就走不下去了。

2、我們需要保證冪等性(無論多少次操作,最後造成的結果和只執行一次造成的結果是一樣的。)
消息肯定會出現重復投遞的問題,這裏應該由消費端去保證,重復的消息不能進行消費

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

代碼實現

!!!註意是在distributed-transaction分支!!!
https://github.com/LinkinStars/MicroServiceExample

參考博客

https://segmentfault.com/a/1190000012762869

具體其他細節這裏講的很清楚,這裏不再贅述,針對分布式事務,一直都是一個難題,當前的解決方案有很多,適應不同的應用場景,所以需要根據實際項目使用場景來選取。

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