使用快取可以緩解大流量壓力,顯著提高程式的效能。我們在使用快取系統時,尤其是大併發情況下,經常會遇到一些「疑難雜症」。本文總結了一些使用快取時常見的問題及解決方案,以後在遇到這類問題時可以作為參考,在設計快取系統的時候也應該考慮這些常見的情況。
為了表述方便,本文以資料庫查詢快取為例,使用快取可以減小對資料庫的壓力。
我們在使用快取時,往往先嘗試去快取中取值,如果沒有,再去資料庫取值,如果資料庫也沒有值,則根據業務需求,返回空或者拋異常。
如果使用者一直訪問乙個資料庫不存在的資料,比如id為-1的資料,就會導致每次請求都會先去快取查一次,然後再去資料庫查一次,造成嚴重的效能問題。這種情況就叫快取穿透。
解決方案
以下幾種解決方案:
快取擊穿指的是,乙個key的訪問量非常大,比如某秒殺活動,有1w/s的併發量。這個key在某一時刻過期,那這些大量的請求就會一瞬間到資料庫,資料庫可能會直接崩潰。
解決方案
快取擊穿的解決方案也有幾種,可以配合使用:
快取雪崩指的是,在某一時刻,多個key失效。這樣就會有大量的請求從快取中獲取不到值,全部到資料庫。還有另一種情況,就是快取伺服器宕機,也算做快取雪崩。
解決方案
針對上述兩種情況,快取雪崩有兩種解決方案:
資源搜尋**大全
在使用資料庫快取的時候,讀和寫的流程往往是這樣的:
所謂雙寫不一致,就是在發生寫操作(更新)的時候或寫操作之後,可能會存在資料庫裡面的值和快取中的值不同的情況。
為什麼更新的時候要先刪除快取,再更新資料庫?因為如果先更新資料庫,然後在刪除快取的時候失敗了,就會造成快取裡面的值和資料庫的值不一致。
然而這樣並不能完全避免雙寫不一致問題。假設在大併發情景下,乙個執行緒先刪除快取,然後取更新資料庫,這個時候另乙個執行緒去取快取,發現沒有值,於是去讀資料庫,然後把資料庫舊的值設定進快取。等第乙個執行緒更新完資料庫後,資料庫裡面就是新的值,而快取裡面是舊的值,所以就存在了資料不一致的問題。
乙個比較簡單的解決辦法是把過期時間設定得比較低,這樣就只有在快取沒過期之前存在資料不一致問題,在一些業務場景下也還能接受。
另一種解決方案是使用佇列輔助。先更新資料庫,再刪除快取。如果刪除失敗,就放進佇列。然後另乙個任務從佇列中取出訊息,不斷去重試刪除相應的key。
還有一種解決方案是使用對乙個資料使用乙個佇列,使讀寫操作序列化。比如對id為n的資料建立乙個佇列。對這條資料的寫操作,刪除快取後,放進乙個佇列;然後另乙個執行緒過來了,發現沒有快取,則把這個讀操作也放進這個佇列裡面。
不過這樣會增加程式的複雜性,序列化也會降低程式的吞吐量,可能得不償失。一般主流的解決方案還是先刪除快取,再更新資料庫。可以滿足絕大部分需求。
redis快取常見問題及解決方案
快取雪崩 當快取伺服器重啟或者大量快取集中在某乙個時間段失效,這樣在失效的時候,會給後端系統帶來很大壓 力。導致系統崩潰。解決方案 在快取失效後,通過加鎖或者佇列來控制讀資料庫寫快取的執行緒數量。比如對某個key只允許乙個線 程查詢資料和寫快取,其他執行緒等待。做二級快取,a1為原始快取,a2為拷貝...
Redis快取常見問題及解決方案
可以簡單的理解為 系統剛剛部署完畢,所有快取資料還未準備完畢或者由於原有快取有效期集體到達 例如 系統中所有快取都設定的一致的過期時間,在同一時刻出現大面積的快取過期,所以原本應該查詢快取的請求都去查詢資料庫了,造成資料庫壓力驟增,甚至宕機.使用加鎖或者佇列的方式保證不會有大量執行緒對資料庫進行一次...
高併發快取常見問題及解決方案
快取穿透是指查詢乙個一定不存在的資料,由於快取是不命中時被動寫的,並且出於容錯考慮,如果從儲存層查不到資料則不寫入快取,這將導致這個不存在的資料每次請求都要到儲存層去查詢,失去了快取的意義。在流量大時,可能db就掛掉了,要是有人利用不存在的key頻繁攻擊我們的應用,這就是漏洞。有很多種方法可以有效地...