java分布式事务——最终一致性,最大努力通知总结!
目錄
源碼地址:https://github.com/kaixuanzhang123/dtx.git
4.分布式事務解決方案之可靠消息最終一致性
?4.1.什么是可靠消息最終一致性事務? ??
4.2.解決方案
5.分布式事務解決方案之最大努力通知
? 5.1.什么是最大努力通知? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
關于CAP,BASE理論,以及TCC,seata解決方案,可以參考我上一篇博客https://blog.csdn.net/zhangkaixuan456/article/details/108210071
源碼地址:https://github.com/kaixuanzhang123/dtx.git
4.分布式事務解決方案之可靠消息最終一致性
?4.1.什么是可靠消息最終一致性事務? ??
? ? 可靠消息最終一致性方案是指當事務發起方執行完成本地事務后并發出一條消息,事務參與方(消息消費者)一定能夠接收消息并處理事務成功,此方案強調的是只要消息發給事務參與方最終事務要達到一致。
? ? 此方案是利用消息中間件完成,如下圖:
? ? 事務發起方(消息生產方)將消息發給消息中間件,事務參與方從消息中間件接收消息,事務發起方和消息中間件之間,事務參與方(消息消費方)和消息中間件之間都是通過網絡通信,由于網絡通信的不確定性會導致分布式事務問題。
? ? ? ? ? ? ? ? ? ? ??
? 因此可靠消息最終一致性方案要解決以下幾個問題:
? 1.本地事務與消息發送的原子性問題
本地事務與消息發送的原子性問題即:事務發起方在本地事務執行成功后消息必須發出去,否則就丟棄消息。即實現本地事務和消息發送的原子性,要么都成功,要么都失敗。本地事務與消息發送的原子性問題是實現可靠消息最
? ? 終一致性方案的關鍵問題。
? ? 先來嘗試下這種操作,先發送消息,再操作數據庫:
? ? 這種情況下無法保證數據庫操作與發送消息的一致性,因為可能發送消息成功,數據庫操作失敗。你立馬想到第二種方案,先進行數據庫操作,再發送消息:
begin?transaction;//1.數據庫操作//2.發送MQ commit?transation;? ? 這種情況下貌似沒有問題,如果發送MQ消息失敗,就會拋出異常,導致數據庫事務回滾。但如果是超時異常,數據庫回滾,但MQ其實已經正常發送了,同樣會導致不一致。
? 2、事務參與方接收消息的可靠性
? ? 事務參與方必須能夠從消息隊列接收到消息,如果接收消息失敗可以重復接收消息。
? 3、消息重復消費的問題
? ? 由于網絡2的存在,若某一個消費節點超時但是消費成功,此時消息中間件會重復投遞此消息,就導致了消息的重復消費。
? ? 要解決消息重復消費的問題就要實現事務參與方的方法冪等性。
4.2.解決方案
? 4.2.1.RocketMQ事務消息方案
? ? ?RocketMQ 是一個來自阿里巴巴的分布式消息中間件,于 2012 年開源,并在 2017 年正式成為 Apache 頂級項目。據了解,包括阿里云上的消息產品以及收購的子公司在內,阿里集團的消息產品全線都運行在 RocketMQ 之上,并且最近幾年的雙十一大促中,RocketMQ 都有搶眼表現。Apache RocketMQ 4.3之后的版本正式支持事務消息,為分布式事務實現提供了便利性支持。
RocketMQ 事務消息設計則主要是為了解決 Producer 端的消息發送與本地事務執行的原子性問題,RocketMQ 的設計中 broker 與 producer 端的雙向通信能力,使得 broker 天生可以作為一個事務協調者存在;而 RocketMQ本身提供的存儲機制為事務消息提供了持久化能力;RocketMQ 的高可用機制以及可靠消息設計則為事務消息在系統發生異常時依然能夠保證達成事務的最終一致性。
? ? 在RocketMQ 4.3后實現了完整的事務消息,實際上其實是對本地消息表的一個封裝,將本地消息表移動到了MQ內部,解決 Producer 端的消息發送與本地事務執行的原子性問題。
? ?執行流程如下:
? ? 為方便理解我們還以注冊送積分的例子來描述 整個流程。
? ? Producer 即MQ發送方,本例中是用戶服務,負責新增用戶。MQ訂閱方即消息消費方,本例中是積分服務,負責新增積分。
? ? 1、Producer 發送事務消息
? ? Producer (MQ發送方)發送事務消息至MQ Server,MQ Server將消息狀態標記為Prepared(預備狀態),注意此時這條消息消費者(MQ訂閱方)是無法消費到的。
? ? 本例中,Producer 發送 ”增加積分消息“ 到MQ Server。
? ? 2、MQ Server回應消息發送成功
? ? MQ Server接收到Producer 發送給的消息則回應發送成功表示MQ已接收到消息。
? ? 3、Producer 執行本地事務
? ? Producer 端執行業務代碼邏輯,通過本地數據庫事務控制。本例中,Producer 執行添加用戶操作。
? ? 4、消息投遞
? ? 若Producer 本地事務執行成功則自動向MQServer發送commit消息,MQ Server接收到commit消息后將”增加積分消息“ 狀態標記為可消費,此時MQ訂閱方(積分服務)即正常消費消息;若Producer 本地事務執行失敗則自動向MQServer發送rollback消息,MQ Server接收到rollback消息后 將刪除”增加積分消息“ 。
? ? MQ訂閱方(積分服務)消費消息,消費成功則向MQ回應ack,否則將重復接收消息。這里ack默認自動回應,即程序執行正常則自動回應ack。
? ?5、事務回查
? ? 如果執行Producer端本地事務過程中,執行端掛掉,或者超時,MQ Server將會不停的詢問同組的其他 Producer來獲取事務執行狀態,這個過程叫事務回查。MQ Server會根據事務回查結果來決定是否投遞消息。
? ? 以上主干流程已由RocketMQ實現,對用戶側來說,用戶需要分別實現本地事務執行以及本地事務回查方法,因此只需關注本地事務的執行狀態即可。
? ? RoacketMQ提供RocketMQLocalTransactionListener接口:
5.分布式事務解決方案之最大努力通知
? 5.1.什么是最大努力通知
? ? 最大努力通知也是一種解決分布式事務的方案,下邊是一個是充值的例子:
? ? ? ? ? ? ? ?
? 交互流程:
? ? 1、賬戶系統調用充值系統接口
? ? 2、充值系統完成支付處理向賬戶系統發起充值結果通知。若通知失敗,則充值系統按策略進行重復通知
? ? 3、賬戶系統接收到充值結果通知修改充值狀態。
? ? 4、賬戶系統未接收到通知會主動調用充值系統的接口查詢充值結果。
? 通過上邊的例子我們總結最大努力通知方案的目標:
? ? 目標:發起通知方通過一定的機制最大努力將業務處理結果通知到接收方。
? 具體包括:
? ? 1、有一定的消息重復通知機制。因為接收通知方可能沒有接收到通知,此時要有一定的機制對消息重復通知。
? ? 2、消息校對機制。
? ? 如果盡最大努力也沒有通知到接收方,或者接收方消費消息后要再次消費,此時可由接收方主動向通知方查詢消息信息來滿足需求。
? ? 最大努力通知與可靠消息一致性有什么不同?
? ? 1、解決方案思想不同
? ? 可靠消息一致性,發起通知方需要保證將消息發出去,并且將消息發到接收通知方,消息的可靠性關鍵由發起通知方來保證。
最大努力通知,發起通知方盡最大的努力將業務處理結果通知為接收通知方,但是可能消息接收不到,此時需要接收通知方主動調用發起通知方的接口查詢業務處理結果,通知的可靠性關鍵在接收通知方。
? ? 2、兩者的業務應用場景不同
? ? 可靠消息一致性關注的是交易過程的事務一致,以異步的方式完成交易。最大努力通知關注的是交易后的通知事務,即將交易結果可靠的通知出去。
? ? 3、技術解決方向不同
? ? 可靠消息一致性要解決消息從發出到接收的一致性,即消息發出并且被接收到。最大努力通知無法保證消息從發出到接收的一致性,只提供消息接收的可靠性機制。可靠機制是,最大努力的將消息通知給接收方,當消息無法被接收方接收時,由接收方主動查詢消息(業務處理結果)。?
? 5.2.解決方案? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? 通過對最大努力通知的理解,采用MQ的ack機制就可以實現最大努力通知。
? ? 方案1:
? ??
? 本方案是利用MQ的ack機制由MQ向接收通知方發送通知,流程如下:
? ? 1、發起通知方將通知發給MQ。使用普通消息機制將通知發給MQ。
? ? 注意:如果消息沒有發出去可由接收通知方主動請求發起通知方查詢業務執行結果。(后邊會講)
? ? 2、接收通知方監聽 MQ。
? ? 3、接收通知方接收消息,業務處理完成回應ack。
? ? 4、接收通知方若沒有回應ack則MQ會重復通知。
? ? MQ會按照間隔1min、5min、10min、30min、1h、2h、5h、10h的方式,逐步拉大通知間隔 (如果MQ采用rocketMq,在broker中可進行配置),直到達到通知要求的時間窗口上限。
? ? 5、接收通知方可通過消息校對接口來校對消息的一致性。
? 方案2:
? 本方案也是利用MQ的ack機制,與方案1不同的是應用程序向接收通知方發送通知,如下圖:
? ??
? 交互流程如下:
? ? 1、發起通知方將通知發給MQ。
? ? 使用可靠消息一致方案中的事務消息保證本地事務與消息的原子性,最終將通知先發給MQ。
? ? 2、通知程序監聽 MQ,接收MQ的消息。
? ? 方案1中接收通知方直接監聽MQ,方案2中由通知程序監聽MQ。通知程序若沒有回應ack則MQ會重復通知。
? ? 3、通知程序通過互聯網接口協議(如http、webservice)調用接收通知方案接口,完成通知。通知程序調用接收通知方案接口成功就表示通知成功,即消費MQ消息成功,MQ將不再向通知程序投遞通知消息。
? ? 4、接收通知方可通過消息校對接口來校對消息的一致性。
? 方案1和方案2的不同點:
? ? 1、方案1中接收通知方與MQ接口,即接收通知方案監聽 MQ,此方案主要應用與內部應用之間的通知。
? ? 2、方案2中由通知程序與MQ接口,通知程序監聽MQ,收到MQ的消息后由通知程序通過互聯網接口協議調用接收通知方。此方案主要應用于外部應用之間的通知,例如支付寶、微信的支付結果通知。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 歡迎關注我的公眾號,一起學習!
? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? 關注「Java源碼進階」,獲取海量java,大數據,機器學習資料!
總結
以上是生活随笔為你收集整理的java分布式事务——最终一致性,最大努力通知总结!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于Page Life Expectan
- 下一篇: JMeter 进行 MD5加密