TCC 強一致性 實時 DEMO 下單(創建訂單,扣除庫存,增加積分,扣除餘額)

僞代碼

場景

用購買某種商品1件(原庫存1000),增加20積分,扣除100元餘額

設計說明

通過日誌表來完成TCC。修改庫存,餘額表要先添加一條記錄到他們的日誌表裏,表要記錄TCC狀態。
通過唯一業務Code去重,保證冪等。
沒有抽象一個活動管理器來管理TCC。

服務

  1. 本地創建訂單服務createOrder
  2. 本地插入訂單Mapper層 insertOrder(orderCode)
  3. 本地其他服務
  4. 遠程服務是否可以扣除庫存ifReduceStock(orderCode,reduceNumber)
  5. 遠程服務是否可以扣除餘額ifReduceBalance(orderCode,sum)
  6. 遠程服務Try扣除庫存,鎖住扣除庫存tryReduceStock(orderCode,reduceNumber)
  7. 遠程服務Try扣除餘額,鎖住扣除餘額tryReduceBalance(orderCode,sum)
  8. 遠程服務增加積分
  9. 遠程服務Confirm扣除庫存confirmReduceStock(orderCode,ReduceNumber)
  10. 遠程服務Confirm扣除餘額ConfirmReduceBalance(orderCode,sum)
  11. 遠程服務Cancel扣除庫存,取消佔有資源cancelReduceStock(orderCode,ReduceNumber)
  12. 遠程服務Cancel扣除餘額,取消佔有資源cancelReduceBalance(orderCode,sum)
  13. 遠程服務增加積分
  14. 遠程其他服務
    補充服務:扣除日誌超過timeOut時間的記錄狀態設置爲失效Cancel(在是否扣除ifReduce,Confirm操作中調用補充服務)

創建訂單服務createOrder描述

這裏寫圖片描述
圖1:創建訂單-活動圖

觸發:用戶點擊下單

本地,檢查

  1. 本地業務服務事務開始
  2. 本地業務服務同步檢查(調用遠程服務是否可以扣除庫存ifReduceStock(orderCode,reduceNumber), 遠程服務是否可以扣除餘額ifReduceBalance(orderCode,sum),其他)
    調用遠程服務是否可以扣除庫存ifReduceStock(orderCode,reduceNumber)說明:
    首先,要調用補充服務把日誌中超過timeOut時間的記錄狀態設置爲失效Cancel。
    其次,要把日誌狀態爲鎖住Try庫存從剩餘庫存剪掉
    餘額同上
  3. 生成訂單Code(orderCode全世界唯一)
  4. 同步本地業務插入訂單Mapper層 insertOrder(orderCode),得到訂單
  5. 其他本地業務

Try

  1. 同步調用遠程服務Try扣除庫存tryReduceStock(orderCode,reduceNumber),鎖住扣除庫存1
    具體:
    遠程添加此次扣除日誌(三種方式:數據庫,Redis,MongoDB),其他判斷是否可以扣除庫存務必減去這個庫存1(從扣除日誌找orderCode相同,狀態爲鎖住Try的操作庫存數)
    數據記錄主要字段,值:
    orderCode(用於去重)
    原庫存,值1000
    此次操作庫存,值1
    操作時間(一個用途,用於計算超過某個值timeOut後,把此條記錄狀態設置爲失效Cancel)
    狀態(鎖住Try,確認Confirm,失效Cancel),值鎖住Try

  2. 同步調用遠程服務Try扣餘額tryReduceBalance(orderCode,sum),鎖住扣除餘額100
    具體同庫存

  3. 同步調用遠程服務Try增加積分
    具體同庫存(比庫存簡單一些)
  4. 有任何錯誤或者異常回滾本地事務。結束。

Confirm,Cancel

  1. 同步調用遠程服務Confirm真正扣除庫存confirmReduceStock(orderCode,ReduceNumber)
    具體:
    首先,要調用補充服務把日誌中超過timeOut時間的記錄狀態設置爲失效Cancel
    其次,扣除日誌裏找到orderCode,此次操作庫存爲ReduceNumber1,狀態爲鎖住Try記錄,根據此條記錄扣減庫存。
  2. 失敗了。1)Cancel扣除庫存,取消佔有資源2)回滾本地事務。結束。
  3. 同步調用遠程服務Confirm扣除餘額ConfirmReduceBalance(orderCode,sum)
  4. 失敗了。
    1)Cancel扣除餘額,取消佔有資源
    2)遠程調用服務Cancel扣除庫存cancelReduceStock(orderCode,ReduceNumber)還原庫存
    具體還原庫存:
    除日誌裏找到orderCode,此次操作庫存爲ReduceNumber1,狀態爲確認Confirm記錄,根據此條記錄還原庫存。
    3)回滾本地事務。結束。
  5. 同步遠程調用增加積分如果失敗同樣要還原庫存和餘額
  6. 本地業務服務事務結束,提交。

問題

1.爲什麼有些地方可以不進行Cancel操作?因爲超過TimeOut會Cancel。
2.秒殺活動等高併發怎麼辦?秒殺情況下,應在下單前的購買和加入購物車操作做限制。添加一個隊列,隊列中請求已把庫存買光,就不允許進入隊列走下單。只有進入隊列的纔可以下單。使用Redis實現。

發佈了39 篇原創文章 · 獲贊 6 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章