1. 程式人生 > >緩存穿透

緩存穿透

family 緩沖 邏輯 壓力 list 當我 分布 過濾 使用

所謂緩存,就是在邏輯代碼和數據庫之間插入那麽一層緩沖層,查詢等操作可以在緩沖層解決,不用再去數據庫操作,以達到緩解數據庫壓力和增加查詢效率的那麽一個緩沖層。從這個角度來看,對於緩存穿透,字面理解就是將這個緩沖層打透,我每次都能直達數據庫,你得緩沖層不起什麽效果,就是這麽一個概念。

網上也有對這個概念的各種解釋,我簡要提取整理一下就是: 查詢一個一定不存在的數據,由於緩存是不命中,數據庫也不存在並且數據庫不存在時不會寫入緩存,導致這個數據每次請求都要到數據庫去查詢,失去了緩存的意義。 這種情況如果少了還可以,如果並發量達到一個高度,可能會給數據庫造成很大壓力,甚至宕機。
當然,有了問題我們就得有解決的方案,目前比較成熟的解決方案主要是兩種:一是空值緩存,二是設置過濾器。簡單介紹一下這兩種方案。
    • 空值緩存:當我們去查詢一個緩存數據,這個數據查不到,就去數據庫查詢,再查不到,如果直接報錯返回,下次再查,還是這麽個循環。比如電商平臺,我們查詢一個商家推薦商品,當前要是沒有推薦,我們每次去查詢該商家的推薦商品,都要去數據庫查詢。設想一下,如果我們第一次在數據庫查詢完沒有查到數據,就在緩存中緩存該商家的推薦商品是空,那麽下一次我們再查詢的時候,是不是就可以直接到緩存層就可以知道該商家沒有推薦商品,而不用去查詢數據庫了。所謂的空值緩存,就是這樣一個邏輯,將第一次查出來的空值,設置在緩存中,以達到緩解數據庫壓力的問題。
    • 設置過濾器,一般是使用一個bitmap(也可以使用一個set集合),將可查的數據放入這個集合當中。再拿商家推薦例子吧,我將有推薦的商家id都放入這個一個集合當中,每次查詢的時候都去這個集合過濾一遍,只有合格的數據,我才去緩存查,不合格的,我就默認他是null就可以了。
      當然過濾方案不止這一種啊,比如像我們要是緩存ip信息,這個字段是有規則的啊,我們可以根據ip規則進行過濾再去查詢,防止惡意攻擊等等。
對於這兩種解決方案,普遍使用的都是第一種,對比來說,第一種和第二種,對數據實時變化要求是不一樣的,空值過濾適用於數據變化頻率較高也可以,而你寫死的set集合,對於變化頻率較高的數據,顯然是不擅長的。而對於維護成本來將,第一種的代碼維護成本也是簡單暴力,第二種則略顯復雜。
寫到這裏,就多扯兩句,關於緩存存在的問題,還有緩存失效和緩存雪崩等問題。緩存失效,很多情況,一個是緩存時間到了,失效了,其次還有服務器關了,沒有作用了。關於緩存雪崩,這個肯定算是事故了,比如緩存宕機了,或者緩存大面積的失效,引起一段時間大量數據直接訪問數據庫,造成極大的壓力,這種情況就叫緩存雪崩。但是目前為止,好像還沒有什麽好的緩存雪崩的解決方案,只能預防為主。預防措施主要有1.使用鎖或者隊列來空值數據庫訪問量,2.使用不失效緩存(長短兩個緩存)和設置緩存時間均勻分布,3.不要同一時間很多緩存都失效等

緩存穿透