緩存相關——緩存穿透、緩存併發、緩存失效、緩存預熱、緩存雪崩、緩存算法

1、緩存穿透web

咱們在項目中使用緩存一般都是先檢查緩存中是否存在,若是存在直接返回緩存內容,若是不存在就直接查詢數據庫而後再緩存查詢結果返回。這個時候若是咱們查詢的某一個數據在緩存中一直不存在,就會形成每一次請求都查詢DB,這樣緩存就失去了意義,在流量大時,可能DB就掛掉了。redis

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

要是有人利用不存在的key頻繁攻擊咱們的應用,這就是漏洞。 
有一個比較巧妙的做法是,能夠將這個不存在的key預先設定一個值。 
好比,」key」 , 「&&」。 
在返回這個&&值的時候,咱們的應用就能夠認爲這是不存在的key,那咱們的應用就能夠決定是否繼續等待繼續訪問,仍是放棄掉此次操做。若是繼續等待訪問,過一個時間輪詢點後,再次請求這個key,若是取到的值再也不是&&,則能夠認爲這時候key有值了,從而避免了透傳到數據庫,從而把大量的相似請求擋在了緩存之中。
數據庫

2、緩存併發緩存

有時候若是網站併發訪問高,一個緩存若是失效,可能出現多個進程同時查詢DB,同時設置緩存的狀況,若是併發確實很大,這也可能形成DB壓力過大,還有緩存頻繁更新的問題。服務器

我如今的想法是對緩存查詢加鎖,若是KEY不存在,就加鎖,而後查DB入緩存,而後解鎖;其餘進程若是發現有鎖就等待,而後等解鎖後返回數據或者進入DB查詢。併發

這種狀況和剛纔說的預先設定值問題有些相似,只不過利用鎖的方式,會形成部分請求等待。框架

3、緩存失效分佈式

引發這個問題的主要緣由仍是高併發的時候,平時咱們設定一個緩存的過時時間時,可能有一些會設置1分鐘啊,5分鐘這些,併發很高時可能會出在某一個時間同時生成了不少的緩存,而且過時時間都同樣,這個時候就可能引起一當過時時間到後,這些緩存同時失效,請求所有轉發到DB,DB可能會壓力太重。高併發

那如何解決這些問題呢? 
其中的一個簡單方案就時講緩存失效時間分散開,好比咱們能夠在原有的失效時間基礎上增長一個隨機值,好比1-5分鐘隨機,這樣每個緩存的過時時間的重複率就會下降,就很難引起集體失效的事件。

4、緩存雪崩

緩存雪崩多是由於數據未加載到緩存中,或者緩存同一時間大面積的失效,從而致使全部請求都去查數據庫,致使數據庫CPU和內存負載太高,甚至宕機。

解決思路:

1,採用加鎖計數,或者使用合理的隊列數量來避免緩存失效時對數據庫形成太大的壓力。這種辦法雖然能緩解數據庫的壓力,可是同時又下降了系統的吞吐量。

2,分析用戶行爲,儘可能讓失效時間點均勻分佈。避免緩存雪崩的出現。

3,若是是由於某臺緩存服務器宕機,能夠考慮作主備,好比:redis主備,可是雙緩存涉及到更新事務的問題,update可能讀到髒數據,須要好好解決。

5、緩存預熱

單機web系統狀況下比較簡單。

解決思路:

1,直接寫個緩存刷新頁面,上線時手工操做下。

2,數據量不大,能夠在WEB系統啓動的時候加載。

3,搞個定時器定時刷新緩存,或者由用戶觸發都行。

分佈式緩存系統,如Memcached,Redis,好比緩存系統比較大,由十幾臺甚至幾十臺機器組成,這樣預熱會複雜一些。

解決思路:

1,寫個程序去跑。

2,單個緩存預熱框架。

緩存預熱的目標就是在系統上線前,將數據加載到緩存中。

6、緩存算法

FIFO算法:First in First out,先進先出。原則:一個數據最早進入緩存中,則應該最先淘汰掉。也就是說,當緩存滿的時候,應當把最早進入緩存的數據給淘汰掉。
LFU算法:Least Frequently Used,最不常用算法。
LRU算法:Least Recently Used,近期最少使用算法。請查看:Memcached之你真正理解LRU嗎(4)

LRU和LFU的區別。LFU算法是根據在一段時間裏數據項被使用的次數選擇出最少使用的數據項,即根據使用次數的差別來決定。而LRU是根據使用時間的差別來決定的。

相關文章
相關標籤/搜索