背景
在平常開發中,我們經常會面對防止重復請求的問題,當服務端對于請求的回應涉及資料的修改,或狀態的變更時,可能會造成極大的危害,重復請求的后果在交易系統、售后維權,以及支付系統中尤其嚴重,但是很多時候,都是指望著前端來限制,比如提交之后,按鈕diseabled之類的,其實這些都是不靠譜的,關鍵時候還是需要后端來校驗,
解決方式
1、基于快取資料狀態的驗證
Redis存盤查詢輕量快速,在request進來的時候,可以先記錄在快取中,后續進來的request每次進行驗證,整個流程處理完成,清除快取,
if (!CacheExtension.getInstance().AddUnique($"{key}_unique", 1, DateTimeOffset.Now.AddDays(365))) { LogExtention.getInstance().WriteCustomLogAsync("", "", true, "上批次還未執行結束"); return ResponseResult.FromError("上批次還未執行結束!"); }
if (!string.IsNullOrEmpty(uniqueKey)) { CacheExtension.getInstance().Remove(uniqueKey); } return ResponseResult.Ok();
2、利用唯一索引機制的驗證
需要原子性操作,想到了資料庫的唯一索引,新建一個表,每次request進來則往表里面插入資料, 操作完成后,洗掉此條記錄,

3、基于快取的計數器驗證
由于資料庫的操作比較消耗性能,了解到redis的計數器也是原子性操作,果斷采用計數器,既可以提高性能,還不用存盤,而且能提升qps的峰值, 每次request進來則新建一個以orderId為key的計數器,然后+1,如果>1(不能獲得鎖): 說明有操作在進行,洗掉,如果=1(獲得鎖): 可以操作,
redis> SET test 20 OK redis> INCR test (integer) 21 redis> GET test # 數字值在 Redis 中以字串的形式保存 "21" //獲取指定的所有計數器 HGETALL counter:user:{userID} //獲取指定的指定計數器 HMGET counter:user:{userID} praiseCnt hostCnt //指定點贊數+1 HINCRBY counter:user:{userID} praiseCnt
總結
1、c#本身有lock機制,單體模式可以使用,
2、但是考慮到我們的分布式部署,建議還是用快取,在大并發的情況下,程式各種情況的發生,特別是涉及到金額操作,所以在大并發要互斥的情況下可以考慮2、3兩種方案,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/264664.html
標籤:.NET技术
