緩存穿透、緩存擊穿、緩存雪崩問題

緩存穿透、緩存擊穿、緩存雪崩問題

​緩存穿透

​ 緩存穿透,是指查詢一個數據庫一定不存在的數據正常的使用緩存流程大致是,數據查詢先進行緩存查詢,如果 key 不存在或者 key 已經過期,再對數據庫進行查詢,並把查詢到的對象,放進緩存。如果數據庫查詢對象爲空,則不放進緩存,就會每次都去查詢數據庫,而每次查詢都是空,每次又都不會進行緩存。假如有惡意攻擊,就可以利用這個漏洞,對數據庫造成壓力,甚至壓垮數據庫,導致所有的請求都懟到數據庫上,從而數據庫連接異常。

解決方案:

  1. 利用互斥鎖,緩存失效的時候,先去獲得鎖,得到鎖了再去請求數據庫。沒得到鎖,則休眠一段時間重試

  2. 採用異步更新策略,無論 key 是否取到值,都直接返回。value 值中維護一個緩存失效時間,緩存如果過期,異步起一個線程去讀數據庫,更新緩存。需要做緩存預熱(項目啓動前,先加載緩存)操作。

  3. 提供一個能迅速判斷請求是否有效的攔截機制,比如,利用布隆過濾器,內部維護一系列合法有效的 key。迅速判斷出,請求所攜帶的 Key 是否合法有效。如果不合法,則直接返回。

  4. 如果從數據庫查詢的對象爲空,也放入緩存,只是設定的緩存過期時間較短,比如設置爲 60 秒。

緩存擊穿

​ 緩存擊穿,是指一個 key 非常熱點,在不停的扛着大併發,大併發集中對這一個點進行訪問,當這個 key 在失效的瞬間,持續的大併發就穿破緩存,直接請求數據庫,就像在一個屏障上鑿開了一個洞。做電商項目的時候,把這貨就稱爲“爆款”。

解決方案:

  1. 從 redis 上看,確實沒有設置過期時間,這就保證了,不會出現熱點 key 過期問題,也就是“物理”不過期。
  2. 從功能上看,如果不過期,那不就成靜態的了嗎?所以我們把過期時間存在 key對應的 value 裏,如果發現要過期了,通過一個後臺的異步線程進行緩存的構建,也就是“邏輯”過期。

緩存雪崩

​ 緩存雪崩,是指緩存同一時間大面積的失效,這個時候又來了一波請求,結果請求都懟到數據庫上,從而導致數據庫連接異常。

​ 產生雪崩的原因之一,比如商城馬上就要到雙十一零點,很快就會迎來一波搶購,這波商品時間比較集中的放入了緩存,假設緩存一個小時。那麼到了凌晨一點鐘的時候,這批商品的緩存就都過期了。而對這批商品的訪問查詢,都落到了數據庫上,對於數據庫而言,就會產生週期性的壓力波峯。

​ 其實集中過期,倒不是非常致命,比較致命的緩存雪崩,是緩存服務器某個節點宕機或斷網。因爲自然形成的緩存雪崩,一定是在某個時間段集中創建緩存,那麼那個時候數據庫也是可以頂住壓力的,無非就是對數據庫產生週期性的壓力而已。而緩存服務節點的宕機,對數據庫服務器造成的壓力是不可預知的,很有可能瞬間就把數據庫壓垮。

解決方案:

​ 做電商項目的時候,一般是採取不同分類商品,緩存不同週期。在同一分類中的商品,加上一個隨機因子。這樣能儘可能分散緩存過期時間,而且,熱門類目的商品緩存時間長一些,冷門類目的商品緩存時間短一些,也能節省緩存服務的資源。

  1. 給緩存的失效時間,加上一個隨機值,避免集體失效。

  2. 使用互斥鎖,但是該方案吞吐量明顯下降了。

  3. 雙緩存。我們有兩個緩存,緩存 A 和緩存 B。緩存 A 的失效時間爲 20 分鐘,緩存 B不設失效時間。自己做緩存預熱操作。然後細分以下幾個小點

    a. 從緩存 A 讀數據庫,有則直接返回

    b. A 沒有數據,直接從 B 讀數據,直接返回,並且異步啓動一個更新線程。

    c. 更新線程同時更新緩存 A 和緩存 B。

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