看完這篇緩存穿透的文章,又能和麪試官互扯了~

前言

  • 昨天有讀者朋友留言,想要陳某寫一篇防止緩存穿透的文章,今天特地寫了一篇。
  • 文章目錄以下:

什麼是緩存穿透?

  • 緩存穿透實際上是指從緩存中沒有查到數據,而不得不從後端系統(好比數據庫)中查詢的狀況。
  • 緩存畢竟是在內存中,不可能全部的數據都存儲在 Redis 中,所以少許的緩存穿透是不可避免的,也是系統可以承受的,可是一旦在瞬間發生大量的緩存穿透,數據庫的壓力會瞬間增大,後果可想而知。
  • 在開發中使用緩存的方案以下圖,在查詢數據庫以前會先查詢 Redis: Redis緩存
  • 緩存穿透的整個過程分爲以下幾個步驟:
    1. 應用查詢緩存,緩存不命中
    2. DB 層查詢不命中,不將空結果緩存
    3. 返回空結果
    4. 下一個請求繼續重複1,2,3步。

解決方案

  • 萬事萬物都是相生相剋,既然出現了緩存穿透,就必定有避免的方案。
  • 下面介紹兩種緩存的方案,分別是緩存空值布隆過濾器

緩存空值

  • 回顧緩存穿透的定義知道,大量空值沒有緩存致使重複的訪問 DB 層,由此解決方案也是很明顯了,直接將返回的空值也緩存便可。此時的執行步驟以下圖:
  • 緩存空值
  • 如上圖所示,若是緩存不命中,查詢 DB 層以後,直接將空值緩存在 Redis 中。僞代碼以下:
Object nullValue = new Object(); try { Object valueFromDB = getFromDB(uid); //從數據庫中查詢數據
  if (valueFromDB == null) { cache.set(uid, nullValue, 10);   //若是從數據庫中查詢到空值,就把空值寫入緩存,設置較短的超時時間
  } else { cache.set(uid, valueFromDB, 1000); } } catch(Exception e) { // 出現異常也要寫入緩存
  cache.set(uid, nullValue, 10); }
 
  • 經過僞代碼能夠很清楚的瞭解了緩存空值的流程,可是須要注意如下問題:
    • 緩存必定要設置過時時間:由於空值並非準確的業務數據,而且會佔用緩存空間,因此要給空值加上一個過時時間,使得可以在短時間以內被淘汰。可是隨之而來的一個問題就是在必定的時間窗口內緩存的數據和實際數據不一致,好比設置 10 秒鐘過時時間,可是在這 10 秒以內業務又寫入了數據,那麼返回就不該該爲空值了,因此還要考慮數據一致的問題,解決方法很簡單,利用消息系統或者主動更新的方式清除掉緩存中的數據便可。

布隆過濾器

  • 1970 年布隆提出了一種布隆過濾器的算法,用來判斷一個元素是否在一個集合中。這種算法由一個二進制數組和一個 Hash 算法組成。
  • 具體的算法思想這裏再也不詳細解釋了,若有不瞭解的能夠看陳某上一篇文章大白話布隆過濾器,又能和麪試官扯皮了~
  • 解決緩存穿透的大體思想:在訪問緩存層和存儲層以前,能夠經過定時任務或者系統任務來初始化布隆過濾器,將存在的 key 用布隆過濾器提早保存起來,作第一層的攔截。例如:一個推薦系統有 4 億個用戶 id, 每一個小時算法工程師會根據每一個用戶以前歷史行爲計算出推薦數據放到存儲層中, 可是最新的用戶因爲沒有歷史行爲, 就會發生緩存穿透的行爲, 爲此能夠將全部推薦數據的用戶作成布隆過濾器。 若是布隆過濾器認爲該用戶 id 不存在, 那麼就不會訪問存儲層, 在必定程度保護了存儲層。此時的結構以下圖:
  • 布隆過濾器
  • 固然布隆過濾器的假陽性的存在致使了誤判率,可是咱們能夠儘可能的下降誤判率,一個解決方案就是:使用多個 Hash 算法爲元素計算出多個 Hash 值,只有全部 Hash 值對應的數組中的值都爲 1 時,纔會認爲這個元素在集合中。
  • 這種方法適用於數據命中不高數據相對固定實時性低(一般是數據 集較大)的應用場景,代碼維護較爲複雜,可是緩存空間佔用少。爲何呢?由於布隆過濾器不支持刪除元素,一旦數據變化,並不能及時的更新布隆過濾器。

兩種方案對比

  • 兩種方案各有優缺點,具體使用哪一種方案仍是要根據業務場景和系統體量來定。具體的區別以下表:
方案 適用場景 維護成本
緩存對象 1. 數據命中不高 2. 數據頻繁變化,實時性高 代碼維護點單、須要過多的緩存空間,數據一致性須要本身實現
布隆過濾器 1. 數據命中不高 2.數據相對固定,實時性低 代碼維護複雜、緩存空間佔用少

總結

  • 至此,如何解決緩存穿透的問題已經介紹完了,以爲寫得不錯的,有所收穫的朋友,點點在看,分享關注一波。
  • 最近很多讀者留言陳某但願我多發一些面試題,這幾天正好在整理大廠面試常問的面試題,後面會陸續發佈,已經發布的面試題有兩篇,分別是【吊打面試官】Mysql 大
  • 廠高頻面試題!!!Redis 高頻面試題及答案。關注陳某,天天都會有面試題更新!!!
相關文章
相關標籤/搜索