一個較爲健壯的下單方案

一個較爲健壯的下單方案

最近在作的一個新項目中,有一個下單兌換的流程。用戶的積分能夠用來兌換物品。數據庫

這個過程當中,須要有幾部分的操做:code

  • 積分表扣除積分
  • 兌換表寫用戶兌換內容、狀態
  • 下單
  • 更新用戶兌換表爲兌換完成狀態

這個流程中須要保證扣除積分後,可以爲成功爲用戶下單。一個服務的調用會出現三種狀態:成功、失敗、超時。超時的狀況下,是沒法肯定下單是否真正成功的,這時要避免重試時重複下單。爲了保證下單流程的健壯性,除了下單接口自己須要作好冪等以外,上層業務自己也須要記錄下單過程當中的狀態流轉,方便進行下單後的邏輯處理,兌換表中須要一個狀態字段,可能存在的幾種狀態爲:blog

  • 1:扣除積分,未下單
  • 2:扣除積分,已經下單
  • 3:扣除積分,完成訂單
  • 4:下單失敗,積分回退

經過數據庫的事務,咱們首先須要保證,下單出現非超時錯誤時,須要回滾下單以前的數據庫操做:接口

「 事務

​        扣除積分

​        寫兌換表,狀態:一、扣除積分、已經下單

」---> 下單失敗,回滾事務

下單成功自不用說,將兌換表中狀態更新爲3便可。當出現下單超時的時候,以上的事務就先不回滾了,經過消息隊列來進行下單重試。消息隊列的重試,也有可能再次出現超時的狀況。隊列的重試是有必定的時間間隔的,例如每隔/10/30/60秒重試一次。若是重試3次失敗,應該有相應的告警出來,這時候通常是下游的訂單服務不可用了。若是在重試下單時,出現了非超時錯誤,那麼這時候應該給用戶回退積分,而且將兌換表的狀態更新爲下單失敗,金幣回退。隊列

重試下單失敗-->積分回退

到這裏其實已經能夠較好地保證用戶下單的健壯性的。可是還有一點,在成功下單後,須要更新用戶的兌換表到狀態3。這個時候有可能會拋出更新數據庫表失敗的異常,致使實際下單成功,但兌換表狀態不一致的狀況。解決的辦法是當更新兌換表失敗拋出異常時,捕獲該異常,再利用消息隊列發出更新數據庫狀態的消息,進行更新重試。整個流程以下所示:事務

(完)消息隊列

相關文章
相關標籤/搜索