【緩存】緩存雪崩、緩存擊穿、緩存穿透

緩存

緩存雪崩

就是緩存層裏的數據同一個時間點失效,那麼這些數據就會集中打向 MySQL。

緩存擊穿

緩存裏有一條數據,一條數據失效後也是穿過了 redis 打到了 MySQL。

緩存擊穿、緩存雪崩屬於緩存穿透的一種特殊表現形式。

緩存穿透

描述

當找 redis 找不到數據時候,就會出現緩存穿透。

低頻率的緩存穿透不可怕,正常現象。

當高頻率的穿透就影響大了。

黑客攻擊的場景,模擬很多客戶端發送 id = -1 的請求。

id = -1 在 redis 中找不到,穿過 redis 找到數據庫,數據處理不過來就崩了(拒絕服務攻擊DDOS)。

解決方案

  • 通過 MySQL 中找不到的值緩存在 redis 中。(黑客太菜了)

    當然第一次查詢 id = -1 的時候可能沒找到穿透了,但是這次我把 id = -1 放在了 redis 中。

    id = -2 再查詢我再放。。。。也是大量的訪問數據庫。(UUID 黑盒 每次生成一個不一樣的 ID)

    這個方案適得其反,redis 一定的數據淘汰策略(LRU、LFU…)如果每次都是 UUID,那麼真正需要緩存的數據就被淘汰了,redis 裏是一些垃圾數據。

  • 過濾器(redis),這個過濾器把 MySQL 裏面的所有 id 號,放在 redis 和 MySQL 的中間(不行),不一定是通過 id 查詢或者 id 過多,這樣就會導致過濾器的效率太低,內存緊張,導致整個鏈路都很慢。

    解決過濾器中數據過多的場景。布隆過濾器,通過一定的錯誤率降低內存的佔用。

    比如 id = 100,傳給 hash 函數,來一個 bin(二進制, size=10) 數組,保證哈希結果在 0-9 之間。。。。。。

    拿到 id = 100,計算出的 hash 相同,就會告訴客戶端你要的數據是有的。

    錯誤發生在計算哈希上,如果布隆過濾器告訴你數據存在,那麼數據不一定存在。如果布隆過濾器告訴你數據不存在,那麼這個數據一定不存在。

    寧可錯殺 3k 不放過一個。發生哈希碰撞就有可能是一次錯誤,數組的長度影響錯誤率

    哈希函數的個數也有關係。布隆過濾器的簡單實現是 3 個 hash 函數計算的三個位置標示一個數據是否存在。哈希函數個數多了反而錯誤率升高。數組長度很長會增加內存佔用。

    【人生中最重要的一個字“度”】,通過算法計算合適的 hash 函數個數和數組長度。通常的布隆過濾器會要求提供允許的錯誤率 fpp 和存儲的數據量 n。然後通過公式計算出數組大小 m 和 hash 函數的個數 k。

    m = - ( n*ln(fpp) ) / ( ln(2) ^2 )

    k = m/n * ln(2)

    遇到刪除數據的情況?如果 id = 100 和 id = 10 的 hash 結果相同,我刪除了 id = 10 的數據,那麼布隆過濾器的這個 hash 結果的位置不能設爲 0,因爲還有數據對應。

    如果場景中有頻繁的數據刪除情況,建議搞一個二維的數組,第二維的數組用來計數。(長度 100億佔用 1GB 左右)

    面試題:文件 A 存了 100 億個URL,B 文件也是 100 億個 URL。只給一個 4GB 內存文件,快速找出 AB 的交集。

    模糊算法

    通過布隆過濾器來計算 A 中的,B 中的 URL,然後找到對應的交集。只需要一次的磁盤 IO 即可。

    精準算法

    A、B 兩個大文件拆分 1000 個放一個文件,分塊計算 hash 值然後對 1000 取餘。然後對A、B的小文件一一比較。拆分成小文件是爲了可以加載入內存中。

    相同 URL 的 hash 值相同,取摸後也相同。所以會出現在 1-1 對應的小文件中。


EOF

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