在日常開發中,咱們常常會面對防止重複請求的問題。當服務端對於請求的響應涉及數據的修改,或狀態的變動時,可能會形成極大的危害。重複請求的後果在交易系統、售後維權,以及支付系統中尤爲嚴重。可是不少時候,都是期望着前端來限制,好比提交以後,按鈕diseabled之類的,其實這些都是不靠譜的。關鍵時候仍是須要後端來校驗。前端
Redis存儲查詢輕量快速。在request進來的時候,能夠先記錄在緩存中。後續進來的request每次進行驗證。整個流程處理完成,清除緩存。redis
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();
須要原子性操做,想到了數據庫的惟一索引。新建一個表,每次request進來則往表裏面插入數據, 操做完成後,刪除此條記錄。shell
因爲數據庫的操做比較消耗性能,瞭解到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