我說分佈式事務之最大努力通知型事務

複製代碼

TCC適用於公司內部對一致性、實時性要求較高的業務場景,而本文咱們講解的「最大努力通知型事務」是爲解決跨網絡、跨服務之間的柔性事務的另外一種解決方案。數據庫

首先看一下最大努力通知型的流程圖,以下圖bash

我說分佈式事務之最大努力通知型事務


咱們根據圖中的內容,逐步分析一下該方案的業務流程。網絡

1. 原理併發

首先闡述一下該方案的原理,根據圖中所示,框架

業務活動的主動方(通知發起方),在完成本地業務活動處理後,會向業務活動被動方發送消息【箭頭1】, 將業務執行結果通知給業務被動方【箭頭4】。這個過程容許消息丟失,若是發生丟失的狀況,服務主動方可以經過重試盡力實現雙方的數據一致性。此處的的重試就體現出了–最大努力 的特色。異步

而後是業務的被動方。業務被動方會暴露一個業務結果接收接口(或者叫回調接口也能夠)給業務主動方【箭頭4】,對收到的通知消息進行必要的校驗,校驗經過後執行本地業務,從而使業務達到閉環。分佈式

同時,因爲主動方對被動方的通知次數是有限的,即咱們不可能無限制的通知,所以業務活動主動方須要提供一個業務查詢補償接口供被動方使用【箭頭5】,被動方會根據定時策略,向業務活動的主動方發起查詢操做,從而對丟失的業務消息達到補償的目的。優化

整個過程當中,業務被動方暴露給主動方的通知接收接口 以及 業務主動方提供給被動方進行查詢操做的接口均須要實現冪等,這樣才能保證數據完整性不會被破壞,從而實現最終一致性。spa

2. 詳解code

接下來,咱們詳細展開對該方案的講解。

在這個方案中,咱們要求被動方的業務處理結果不能影響業務主動方的處理,雙方的職責是清晰的,例如:咱們接入支付寶的支付功能,我方的身份即業務被動方,而支付寶方則爲業務主動方。

我方接收到用戶的支付請求,等待用戶輸入支付密碼,用戶支付確認後,我方向支付寶發起支付請求,同步返回給用戶預支付結果。此時,用戶看到支付處理中。

當支付寶側執行轉帳完成以後(圖中的箭頭1),結果能夠是成功/失敗,總之主動方必定是在本地業務有肯定的執行結果後,纔會發起通知。

支付寶側會經過某種機制(猜測是圖中的消息隊列機制)將通知請求扔到通知消息服務中,通知發送核心業務消費通知消息,並記錄持久化消息到數據庫中,發送通知消息給我方。

我方支付回調接口收到支付完成通知後,會對參數進行簽名校驗,待簽名經過後,取出業務參數,對這筆支付訂單返回的結果進行後續操做(修改狀態爲下單完成併發貨或者修改成支付失敗,操做回滾/退款)。

這個過程理想狀態下是很快的,因爲支付寶側強大的處理能力,咱們幾乎感受不處處理中狀態,但整個過程確實是異步的過程。

【這裏給咱們的啓示之一即是,對於跨系統的交互,若是可以將同步的業務操做拆分爲異步過程,可以大幅度提升業務的靈活度及吞吐量。】


這裏存在一種廣泛的狀況,咱們的系統處理能力是有限的,在收到通知後未能及時的處理完成,這時,雙方會約定,若是收到通知且處理完成,業務被動方須要返回肯定某個狀態碼,如:「success」,不然認爲這次通知失敗。

這樣,只要咱們處理完成就返回「success」,主動方就不會繼續通知。不然,主動方會按照必定策略,好比「時間衰減策略」,對通知失敗的請求從持久層中取出,好比:24小時內,按照間隔1min、5min、10min、30min、1h、2h、5h、10h的方式,逐步拉大通知間隔,直到達到通知要求的時間窗口上限。這時,就須要被動法主動發起查詢。通常這種狀況不多,而這麼作的目的也是爲了使最近的請求更快的被通知回去,咱們認爲,時間越靠後,通知成功的可能性越少,由於大多數的通知請求在第一次通知發起時就返回了成功success。

PS:這裏還有一種措施,就是人工干預,重置通知位點。好比:若是達到最大通知次數依然沒有通知成功,那麼數據仍舊保存在通知庫裏面,運營人員在接收到商戶的重複通知需求的時候,經過人工的操做,從新重置通知次數,這樣消息就能夠從新通知了。

這種狀況每每是業務被動方未接入主動查詢致使的,不建議頻繁採用此方案,正常的流程時在開發階段就強烈要求被動方將通知接口及查詢接口均開發完成。

說多了都是淚,筆者曾經在工做中從事過一段時間商戶接入工做,就遇到過這種類型的商戶,常常要求咱們爲他們從新發起通知,對工做效率的影響真是肉眼可見的。


咱們說回正題,在異常狀況下,若是業務主動方在必定時間閾值內未能及時的發起通知,而做爲業務被動方的咱們又想及時獲取到業務結果,這時就須要業務被動方主動發起查詢,調用主動方暴露的查詢接口獲取業務結果,這裏通常採用定時做業輪詢,從而在業務上達到閉環, 最大可能的保證了數據的一致性。

3. 方案評價

  1. 方案成本:該方案成本較低,主要花費在業務查詢與校對系統建設成本。校對系統是單獨的,例如離線的文件對帳方式,經過雙方定時導出日訂單,作線下的互相對帳,從而實現平帳操做。
  2. 適用範圍:本方案適用於對時間敏感性較低的業務,好比充值、轉帳業務,在內部系統間就不適合該方式。多適用於跨系統、跨業務、跨網絡的服務間數據一致性保證場景。
  3. 用到的服務模式爲: 可查詢操做,冪等操做等。
  4. 方案特色:
  5. 業務活動的主動方在完成業務處理後,向被動方發送通知消息(容許消息丟失);
  6. 主動方能夠設置時間階梯型通知規則,在通知失敗後按規則重複發起通知,直到通知N次後再也不通知
  7. 主動方提供校對查詢接口給被動方,被動方按需校對查詢,用於恢復丟失的業務消息
  8. 應用案例
  9. 支付渠道接入通知,銀行轉帳通知、商戶通知等
  10. 對帳通知(實時/定時)


4. 實現方式

從本文開始的圖中能夠看出,一般採用兩種方式實現

  • 定時任務,使用定時做業輪詢發起直接通知,通知數據要作持久化操做。幾乎無外部依賴。
  • 定時消息隊列,基於定時消息發起通知,一樣須要對通知請求數據作持久化操做,對消息隊列有高可用需求。


5. 如何優化


  1. 在業務系統外增長業務管理系統,對通知失敗數據進行管理,實現手動觸發重複通知操做。
  2. 將通知服務通用化,框架化,剝離通知邏輯與業務邏輯, 對通知隊列進行區分, 不一樣隊列使用不一樣通知規則,而且支持通知策略的可配置性操做等。
  3. 保證通知服務的可用性,必要時創建獨立的數據庫,這裏要注意對通知數據的持久化策略,以及通知失敗後從新發起通知的策略的優化,好比時間衰減策略的設置等。這對通知的成功率和實效性有很大影響。
  4. 要求主動方提供的業務查詢接口及被動方暴露的通知處理業務接口均要實現冪等性。
  5. 最後要注意,內存調優與流量控制,這裏主要針對業務主動方,若是通知消息的生產方的速率與通知發送側的消費方的消費速率不匹配,會致使大量消息駐留在消費端內存中,致使消息服務響應慢,甚至掛掉,從而影響到服務被動方進行業務後續處理,致使更大的商業糾紛等。(這裏再插一句,考慮到極端狀況,若是真的出現down機,在服務重啓後,要能恢復現場,所以對通知消息的持久化操做就是必不可少的。當服務重啓後,通知服務可以定位到上次的消費位點,繼續通知操做)
我說分佈式事務之最大努力通知型事務

6. 小結


本文對分佈式事務解決方案的– 最大努力通知型 柔性解決方案進行了較爲詳細的講解,結合實例及筆者的工做經歷,對方案的各個細節展開講解,但願可以對讀者有所幫助。

後續筆者會着手開發一款分佈式事務的輪子,入手點將採用本文提到的模式,並最終達到基本可用。算是立了一個flag吧,完成以後會第一時間發文出來。(又一個有生之年系列)

到目前爲止,《我說分佈式事務》 系列就過半了,以後我會對可靠消息一致性方案進行講解,咱們不見不散。

相關文章
相關標籤/搜索