高併發系統設計十三-緩存穿透的解決方案

緩存的使用三-緩存穿透了如何解決

在低緩存命中率的系統中,大量查詢請求會穿透緩存到數據庫,因爲數據庫對於併發的承受能力比較脆弱,導致查詢變慢,大量請求阻塞在數據庫查詢上,造成應用服務器的連接和線程資源被佔滿,導致系統崩潰。

1、緩存穿透的解決方案

場景一

通過用戶ID查詢用戶的信息,緩存策略採用 Cache Aside 策略,如果讀取一個用戶表中未註冊的用戶會發生什麼情況,我們會先讀緩存再穿透讀數據庫。由於用戶不存在,所有緩存和數據庫中都沒有查詢到數據,因此也就不會想緩存中回種數據。當再次請求這個用戶數據的時候就會再次穿透到數據庫。

解決方案:回種空值以及使用布隆過濾器

1.1、回種空值

場景一中出現的問題,數據庫中並不存在用戶的數據,就造成了無論查詢多少次數據庫中永遠不會存在這個用戶的數據,穿透就一直會存在。

當從數據庫中查詢到空值或者發生異常時,我們可以向緩存中回種一個空值,但是考慮到佔用緩存的空間,所以可以給空值加一個比較短的過期時間。

1.2、使用布隆過濾器

布隆過濾器的算法,用來判斷一個元素是否在一個集合中。這種算法由一個二進制數組和一個 Hash 算法組成。

思路:

我們把集合中的每一個值按照提供的 Hash 算法算出對應的 Hash 值,然後將 Hash 值對數組長度取模後得到需要計入數組的索引值,並且將數組這個位置的值從 0 改成 1。在判斷一個元素是否存在於這個集合中時,你只需要將這個元素按照相同的算法計算出索引值,如果這個位置的值爲 1 就認爲這個元素在集合中,否則則認爲不在集合中

還是以存儲用戶信息的表爲例進行講解。首先我們初始化一個很大的數組,比方說長度爲 20 億的數組,接下來我們選擇一個 Hash 算法,然後我們將目前現有的所有用戶的 ID 計算出 Hash 值並且映射到這個大數組中,映射位置的值設置爲 1,其它值設置爲 0。

新註冊的用戶除了需要寫入到數據庫中之外,它也需要依照同樣的算法更新布隆過濾器的數組中相應位置的值。那麼當我們需要查詢某一個用戶的信息時,先查詢這個 ID 在布隆過濾器中是否存在,如果不存在就直接返回空值,而不需要繼續查詢數據庫和緩存,這樣就可以極大地減少異常查詢帶來的緩存穿透。

1、選擇多個 Hash 函數計算多個 Hash 值,這樣可以減少誤判的機率;


2、布隆過濾器會消耗一定的內存空間,所以在使用時需要評估你的業務場景下需要多大的內存,存儲的成本是否可以接受。

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