來說說緩存穿透、緩存擊穿、緩存雪崩都是什麼?怎麼解決?

前言

看到題目就知道了,這又是我在面試中遇到的,最近面試,把我的博文質量感覺都提上來了。面一次試感覺夠我總結一週的,但還是每次都能遇到知識盲點,那以後就當面試總結是個掃盲的過程吧。

緩存穿透

面試的時候就被問到了這個問題,具體描述就是,正常的請求都是先請求到緩存(就當我們的緩存是Redis吧),如果緩存中存在數據,就直接返回,如果緩存中不存在請求的數據,就查詢數據庫,然後將查詢到的數據再放到緩存中。

那麼如果現在有一堆的請求,在緩存中沒有,數據庫中也沒有,怎麼辦?這種垃圾請求還特別多,而且因爲是在數據庫沒有查詢到,所以也不會被放到緩存中,這就是緩存穿透的場景。

大量的這種請求,最終會導致數據庫壓力劇增,最終就會將數據打垮,若是這個數據庫是核心數據庫,那麼其他所有依賴這個庫的接口都會報錯。

在這裏插入圖片描述
例如,每次請求的參數都是id,而id是我們數據庫裏的自增主鍵,但是請求過來的參數要麼是-1這種,要麼就是特別大的一個數,反正就是不存在的數據。

解決緩存穿透

那麼如何解決緩存穿透呢?

  • 首先最基本的就是要做參數校驗,非法的參數就直接return,連緩存層都到不了。
  • 當請求的數據在穿過Redis後,數據庫也返回空,這樣的數據也可以存入到緩存中,然後過期時間可以設置一個比較短的時間,這樣能夠在一定程度上保障後端數據庫的安全。
  • 可以使用Redis的布隆過濾器,這個工具可以有效的防止緩存穿透的發生,我們可以將一個參數是否存在保存爲一個boolean值,然後需要一個bit就可以存儲,這樣的數據壓縮到一個數據結構中,就是布隆過濾器的原理。即節省存儲空間,又能達到效果。

緩存擊穿

我們在Redis存儲的數據,主要是緩存的效果,目的是爲了解決DB的壓力,所以一些熱點數據,都是先從緩存中獲取的,當緩存中不存在的時候再從DB中獲取然後再存入緩存。

但是如果一個高頻的熱點數據,在失效的一瞬間,它的大量請求就會直接打到DB上,這樣在DB還沒有返回數據給Redis的時候,DB承受了熱點請求的壓力,就好像緩存是一個水桶,然後突然水桶破了一個洞,直接沖垮了後面的堤壩(DB)。

在這裏插入圖片描述

解決緩存擊穿

造成緩存擊穿的原因是,在同一時刻從數據庫中獲取了大量數據,並且設置了相同的過期時間,這些緩存就會在同一時刻失效,這樣就造成了緩存擊穿的問題。
解決方案

  • 一些熱點的數據,我們可以設置永不過期;或者是在訪問數據的時候延長過期時間
  • 也可以用分佈式鎖,來鎖住數據,保證同一時間只有一個線程能夠獲取數據,其他請求獲取不到數據,只能等待,但是在高併發的場景下,這種方案,體驗不太好,並且分佈式鎖的壓力也會特別大

緩存雪崩

Redis中存儲了很多的數據,但是有時候這些數據會出現,在同一個時刻批量過期的情況,因爲有可能這些數據是批量插入的,所以他們的過期時間就會都在同一個時間。

正好在這個批量數據過期的時間點,大量的請求過來了,因爲緩存數據過期了,所以沒有命中緩存,直接請求到了數據庫中。數據庫的壓力突然劇增,甚至有可能直接撐不住掛掉。然後有可能DBA會緊急重啓DB,但是剛一恢復,新的請求立馬又把DB打垮了。

也有可能就是Redis掛了,緩存都不能用了,請求也是直接打到了DB上,然後DB也是扛不住壓力,直接掛掉。再恢復,再掛掉。
在這裏插入圖片描述
Redis中同一時刻大量的Key過期,那一瞬間和Redis不存在一樣,還有Redis真的掛了的情況,這對服務和DB來說是災難性的問題。

解決緩存雪崩

解決方案

  • 批量存入緩存的數據,我們可以爲這些數據分別配置比較合理的過期時間,即使是隨機分配過期時間也可以,避免同一時間失效。
  • 熱點數據永不過期,更新操作時直接更新緩存,但是並不設置過期時間。
  • 當數據庫緩存出問題時,可以採用降級措施,雖然是用DB頂上了請求,但是可以通過降級方案,保證某些數據在同一時刻只能有一個線程在查詢數據庫和寫緩存,這樣不至於把數據庫給搞崩了。
  • 還有就是爲了防止Redis掛了,導致的緩存雪崩,可以保證Redis的高可用,就是將Redis集羣部署,然後將熱點數據都分配到不同的節點上,這樣就可以有效的防止雪崩的出現。

當說到Redis高可用的時候,面試有可能會繼續問,怎麼保證Redis在高可用的情況下,也就是集羣中的數據同步時,而數據不會丟失等情況。
這個我準備下一篇來繼續啃。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章