相信做web的,都有可能遇到有多次重複請求傳送到後端的情況。而這些重複請求,可能大都是由於在網路較差的情況下,使用者多次連續點選。最後導致後端面臨處理大量重複請求的境地。阻止這些情況發生的方法有很多。
比如在前端,可以設定當使用者點選按鈕之後,禁用按鈕直到有結果返回。如果是用ajax傳送請求,那麼在傳送請求之前,可以呼叫xmlhttprequest的abort()函式,abort 函式是清除上乙個xmlhttprequest 重置為 readystate 為 0 的狀態,並且取消所有未決的網路活動,等等。
在後端,可以用訊息佇列,或者快取,過濾掉相同的請求,也可以設定請求時間間隔。在乙個請求執行完一段時間之後才可以執行下乙個相同的請求,就當於不休息不給幹活。也可以每次都執行你傳送的最後乙個請求,多次請求只執行最後一次。
以上是比較常見的一些方法。然後我遇到的問題,用這些方法卻不能很好的解決。
解決:我只想用後端的方式解決,那麼很顯然,只執行第乙個請求,後面的都忽略。一開始設定了一層快取:
//設定一層快取,來阻止大量的相同的訪問。
datetime result;
if(!_memorycache.trygetvalue(cachekey,out
result))
));//執行建索引的**
}
第乙個請求進來,會為它建立快取,後面的請求進來會先查詢快取中是否有相同的請求。如果有,那就不執行,那麼問題來了,後面的請求不執行檢索,那它應該立即返回嗎?如果立即返回的話,那麼前端會認為索引已經建好了,就開始呼叫搜尋的介面,最後搜尋的結果自然是空的。也不能不返回,那樣就會報超時的錯誤。
後來看到網上的一句話:對於高併發或者分布式的場景 重複的請求最好是不要阻塞 通過判斷鎖狀態直接返回處理狀態就好
意思就是,後面請求應該是去看它要執行的**是否正在被執行,如果正在被執行,就返回索引正在維護,如果執行完了就返回索引已經建好,它本身不回去執行。所以我設計了一下,讓後面的請求都擱置,知道索引建完,然後再返回。當然這裡最好的辦法應該是:返回索引正在維護,並且對維護索引的**上鎖。
修改之後的**:
//設定一層快取,來阻止大量的相同的訪問。
datetime result;
if(!_memorycache.trygetvalue(cachekey,out
result))
));//建索引**
console.writeline(
"索引建好了");
//如果索引成功建完
_memorycache.set(buildkey, "ok
", new
memorycacheentryoptions()
.setabsoluteexpiration(timespan.fromdays(
0.8))
.setslidingexpiration(timespan.fromdays(
0.8))
.registerpostevictioncallback((key, value, reason, state) =>));
}else
}}
我用了乙個無限迴圈,暴力等待索引建好。這樣很多請求過來,只有乙個請求在執行,並且等第乙個請求執行完之後,全部返回同樣的結果。這樣,這種併發的情況就可以處理好了。
cpu也沒有報警。
利用redis快取解決高併發下後端重複請求措施
最近在進行壓力測試的時候發現在高併發下,有些介面很可能因為重複請求導致對資料庫操作出來的資料不是你想要的那個樣子。比如,使用者簽到,你只想讓使用者一天簽到一次,為了防止簽到多次,你對於每次強求,都去查詢資料庫今天是不是已經簽到了,如果簽了,就不讓繼續簽到,如果沒簽到,插入簽到資料,更新積分資料什麼的...
php高併發狀態下檔案的讀寫
背景 1 對於pv不高或者說併發數不是很大的應用,不用考慮這些,一般的檔案操作方法完全沒有問題 2 如果併發高,在我們對檔案進行讀寫操作時,很有可能多個程序對進一檔案進行操作,如果這時不對檔案的訪問進行相應的獨佔,就容易造成資料丟失 對於這樣的問題,一般的解決方案 1 當一程序對檔案進行操作時,首先...
讀 寫鎖的實現和應用(高併發狀態下的map實現)
程式中涉及到對一些共享資源的讀和寫操作,且寫操作沒有讀操作那麼頻繁。在沒有寫操作的時候,兩個執行緒同時讀乙個資源沒有任何問題,所以應該允許多個執行緒能在同時讀取共享資源。但是如果有乙個執行緒想去寫這些共享資源,就不應該再有其它執行緒對該資源進行讀或寫 譯者注 也就是說 讀 讀能共存,讀 寫不能共存,...