最近在進行壓力測試的時候發現在高併發下,有些介面很可能因為重複請求導致對資料庫操作出來的資料不是你想要的那個樣子。比如,使用者簽到,你只想讓使用者一天簽到一次,為了防止簽到多次,你對於每次強求,都去查詢資料庫今天是不是已經簽到了,如果簽了,就不讓繼續簽到,如果沒簽到,插入簽到資料,更新積分資料什麼的。但是資料庫操作是有時間的,在高併發下這種方式明顯是不能限制重複請求提交的,有可能乙個使用者一天簽到好幾次,只要這個提交時間在很短的範圍內就行(親測確實是這樣的)。
於是就引出了今天要討論的問題,如何處理重複提交的問題。
首先看看準確的出現重複請求問題的原因(容老夫ctrl+v一段文字):
在業務開發中,我們常會面對防止重複請求的問題。當服務端對於請求的響應涉及資料的修改,或狀態的變更時,可能會造成極大的危害。重複請求的後果在交易系統、售後維權,以及支付系統中尤其嚴重。
前台操作的抖動,快速操作,網路通訊或者後端響應慢,都會增加後端重複處理的概率。
前台操作去抖動和防快速操作的措施,我們首先會想到在前端做一層控制。當前端觸發操作時,或彈出確認介面,或disable入口並倒計時等等,此處不細表。
但前端的限制僅能解決少部分問題,且不夠徹底,後端自有的防重複處理措施必不可少,義不容辭。
嗯,囉嗦的原因交代完畢,下面來講講具體的solution:
我們說是基於redis快取的處理重複請求的方式,重複請求就是在很短的時間內傳送多次請求,這個時間是相當短的,以至於你進行資料庫查詢來驗證都沒法取阻擋。這樣的話,我們就可以使用乙個快取的計數器來阻止這個問題的發生。在介面的開始,定義乙個快取計數器(該快取的時間可以是幾秒,幾十秒或者一兩分鐘,能完成短時間內多個請求的這個短時間的時間就行),同乙個會員的每個進來乙個請求就將這個計數器+1(當然就是用會員的id+一些特定的字串做key),對於大於1的請求不予受理。這樣在這個快取進行的時間段內就能唯一確保只有乙個。嗯,具體的實現方式就是這樣。(親測有效)
下面推薦幾種處理方式(基本上還是redis快取機制最好,當然我也是主要從這裡借鑑的):
高併發下快取技術應用
背景 在某些電商促消活動中需要搞活動,對某些頁面的訪問量 qps 往往會非常高。如果直接讀資料庫,肯定db會承受不住。那比較常見的方案就是讓大部分相同資訊的請求都盡可能壓在cache上來緩解db的壓力,從而盡可能去滿足高併發訪問的需求 優化 這種快取技術一般用於不會經常變動資訊,並且訪問次數較多的頁...
高併發下快取失效問題
快取穿透 指查詢乙個一定不存在的資料,由於快取是不命中,將去查詢資料庫,但是資料庫也無此記錄,我們沒有將這次查詢的null寫入快取,這將導致這個不存在的資料每次請求都要到儲存層去查詢,失去了快取的意義 風險 利用不存在的資料進行攻擊,資料庫瞬時壓力增大,最終導致崩潰 解決 null結果快取,並加入短...
高併發下快取失效問題
1.快取穿透 查詢乙個一定不存在的資料,由於快取一定不命中,將查詢資料庫,並且沒有將null寫入快取,這將導致這個不存在的資料每次請求都到儲存層查詢。風險 利用不存在的資料進行攻擊,資料庫瞬時壓力增大,最終導致崩潰。解決方案 null結果快取,並加入短暫過期時間。2.快取雪崩 指設定快取時key採用...