分散式事務解決方案—獨立訊息服務
在這裡,首先先簡單介紹一下什麼叫做獨立訊息服務?獨立訊息服務是指:在分散式架構系統當中各個子系統之間相互呼叫而產生的事物問題的一種解決方案,它提供相應介面服務api供訊息生產方,跟訊息消費方使用,從而儘可能的達到事物強一致性保證,下面我們將介紹獨立訊息服務的實現!
舉一個使用者下單支付的例子,我們有一個支付網關係統,在接收到第三方回撥通知成功的情況下,我們訂單系統需要update訂單表為已支付,並insert支付流水,在會員賬戶系統,我們需要往會員賬戶加餘額,記錄賬戶流水等等...
首先,先介紹獨立訊息服務由幾個子系統組成:
1、訊息服務子系統 :主要提供以下作用
a、用於儲存預傳送訊息
b、確認併發送訊息
c、查詢狀態確認超時的訊息
d、確認訊息已被成功消費
e、查詢訊息確認超時的訊息
f、刪除本地訊息(已完成)
2、MQ實時訊息服務子系統 :mq訊息佇列
3、訊息狀態確認子系統 :用於輪詢 or 定時任務查詢生產方訊息投遞異常的記錄,進行重新投遞。
4、訊息恢復子系統 :用於輪詢 or 定時任務查詢 消費端消費失敗的異常日誌記錄,進行消費恢復。
下面介紹正向流程:
第一步:使用者呼叫網關係統,通過網關係統通過訂單系統確認並建立一條待支付的訂單,
第二步:使用者微信掃碼完成支付,
第二步:網關係統接收到微信回撥通知,呼叫實時訊息服務(mq)投遞一條訂單佇列訊息。
第三步:訂單系統監聽到實時訊息服務mq,呼叫訊息服務子系統 儲存一條預傳送的訊息(更新賬戶)到訊息服務子系統的DB儲存。
第四步:訊息服務子系統儲存訂單系統發來了的預傳送訊息存到本地DB,並返回儲存的結果。
第五步:訂單系統得到訊息服務子系統本地儲存成功之後,訂單系統開始執行本地事物(更新訂單狀態、並insert支付流水記錄),並再次呼叫訊息服務子系統告知訂單處理成功的結果,
第六步:訊息服務子系統得到訂單處理完成的結果之後,會更新剛才存在本地的那條預傳送的訊息(更新賬戶)的狀態,改為可傳送。並通過呼叫實時訊息服務(mq)投遞一條更新會員賬戶的訊息佇列。
第七步:會員系統監聽到隊列當中的一條更新賬戶的訊息之後,會執行本地更新賬戶,並將佇列中的更新賬戶訊息刪除掉,再呼叫訊息服務子系統,確認已消費,並刪除這條已被消費的訊息記錄。
異常流程:
1、在第三步中,我呼叫訊息服務子系統 儲存一條預傳送的訊息(更新賬戶)到訊息服務子系統的DB儲存的介面當中,如果網路終端導致介面呼叫失敗,或者呼叫成功但一直得不到訊息服務子系統的一個儲存結果?
答:呼叫失敗/收不到反饋結果,本地事物也不會處理。
2、在第五步中,如果訂單系統收到訊息服務子系統的預傳送訊息DB儲存成功結果,然後進行本地訂單處理的事物也成功/失敗,但是由於網路原因,再次呼叫訊息服務子系統告知訂單處理成功的結果的這個動作失敗,下面流程怎麼走?
答:訊息狀態確認子系統就是來解決這種異常,它會去輪詢訊息日誌表,根據規則找出預傳送狀態的訊息記錄,然後去呼叫訂單系統確認是否已經訂單處理完成,如果訂單處理失敗,則呼叫訊息服務子系統將這條訊息記錄刪除掉,如果訂單處理是完成的,則呼叫正向流程的第六步。
3、在第六步當中,呼叫實時訊息服務(mq)投遞一條更新會員賬戶的訊息佇列失敗,怎麼處理?
答:訊息恢復子系統就是來解決這種異常,它會去輪詢訊息日誌表,根據規則找出訊息狀態為傳送成功,但是還未被消費掉的訊息記錄,然後重新投遞一條消費會員的佇列到實時訊息服務(mq)中,然後執行正向流程的第七步。
4、在第七步當中,如果會員賬戶已經本地事物完成,但是呼叫訊息服務子系統更新狀態為已被消費這個動作失敗了,該怎麼處理?
答:訊息恢復子系統同樣會去輪詢訊息日誌表,根據規則找出訊息狀態為傳送成功,但是還未被消費掉的訊息記錄,然後重新投遞一條消費會員的佇列到實時訊息服務(mq)中,會員系統監聽到佇列之後,本地需要做一個更新賬戶冪等性的判斷,判斷是否已經被處理,如果是處理完成,則再次刪除訊息佇列,並呼叫訊息服務子系統,告知已經被消費。
其它
可能會有讀者問到為什麼要單獨部署兩個定時任務的系統(訊息狀態確認子系統、訊息恢復子系統)? 仔細研究會發現,一個是用來確認生產方的一個流程,一個是用來確認並恢復消費方的一個流程,單獨部署可以做到低耦合。
後面會更新其它關於分散式事物解決的方案,例如 最大努力通知型、TCC階段提交。