<轉>淺談緩存擊穿、緩存並發和緩存失效


原文地址:緩存穿透、緩存並發、緩存失效之思路變遷

 

我們在用緩存的時候,不管是Redis或者Memcached,基本上會通用遇到以下三個問題:

緩存穿透

緩存並發

緩存失效

一、緩存穿透

 
 

 

注:
上面三個圖會有什么問題呢?

我們在項目中使用緩存通常都是先檢查緩存中是否存在,如果存在直接返回緩存內容,如果不存在就直接查詢數據庫然后再緩存查詢結果返回。

這個時候如果我們查詢的某一個數據在緩存中一直不存在,就會造成每一次請求都查詢DB,這樣緩存就失去了意義,在流量大時,可能DB就掛掉了。

那這種問題有什么好辦法解決呢?

要是有人利用不存在的key頻繁攻擊我們的應用,這就是漏洞。

有一個比較巧妙的作法是,可以將這個不存在的key預先設定一個值,比如,"key" , “&&”。

在返回這個&&值的時候,我們的應用就可以認為這是不存在的key,那我們的應用就可以決定是否繼續等待繼續訪問,還是放棄掉這次操作。

如果繼續等待訪問,過一個時間輪詢點后,再次請求這個key,如果取到的值不再是&&,則可以認為這時候key有值了,從而避免了透傳到數據庫,從而把大量的類似請求擋在了緩存之中。

 

二、緩存並發

有時候如果網站並發訪問高,一個緩存如果失效,可能出現多個進程同時查詢DB,同時設置緩存的情況,如果並發確實很大,這也可能造成DB壓力過大,還有緩存頻繁更新的問題。

我現在的想法是對緩存查詢加鎖,如果KEY不存在,就加鎖,然后查DB入緩存,然后解鎖;其他進程如果發現有鎖就等待,然后等解鎖后返回數據或者進入DB查詢。

這種情況和剛才說的預先設定值問題有些類似,只不過利用鎖的方式,會造成部分請求等待。

 

三、緩存失效

引起這個問題的主要原因還是高並發的時候,平時我們設定一個緩存的過期時間時,可能有一些會設置1分鍾啊,5分鍾這些,並發很高時可能會出在某一個時間同時生成了很多的緩存,

並且過期時間都一樣,這個時候就可能引發一當過期時間到后,這些緩存同時失效,請求全部轉發到DB,DB可能會壓力過重。

那如何解決這些問題呢?

其中的一個簡單方案就時講緩存失效時間分散開,比如我們可以在原有的失效時間基礎上增加一個隨機值,比如1-5分鍾隨機,這樣每一個緩存的過期時間的重復率就會降低,就很難引發集體失效的事件。

我們討論的第二個問題時針對同一個緩存,第三個問題時針對很多緩存。

 

總結來看:

1、緩存穿透:查詢一個必然不存在的數據。比如文章表,查詢一個不存在的id,每次都會訪問DB,如果有人惡意破壞,很可能直接對DB造成影響。

2、緩存失效:如果緩存集中在一段時間內失效,DB的壓力凸顯。這個沒有完美解決辦法,但可以分析用戶行為,盡量讓失效時間點均勻分布。

   當發生大量的緩存穿透,例如對某個失效的緩存的大並發訪問就造成了緩存雪崩。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM