緩存穿透星掰、緩存擊穿多望、緩存雪崩區(qū)別和解決方案
有很多解決高并發(fā)的應(yīng)用場景中都會使用memcache\redis緩存來解決響應(yīng)慢的問題,但是緩存也不是萬能的氢烘,在使用方面有很多的考慮的問題怀偷,把緩存比喻成防彈衣,但是如果你沒有穿好這件防彈衣會適得其反播玖,下面我根據(jù)自己的理解就展開來談?wù)劇?/p>
在高并發(fā)場景下有一個常常被忽略的一個地方椎工,讀多還是寫多,讀多寫少用緩存蜀踏,寫多讀少用隊列维蒙。
為什么要用緩存?為了系統(tǒng)的高性能,在每個系統(tǒng)的性能指標(biāo)中有兩個重要的點果覆,一個是性能最佳點和性能最大值颅痊,超過最大融載值就走向系統(tǒng)崩潰的邊緣了。
緩存穿透
緩存穿透是指緩存和數(shù)據(jù)庫中都沒有的數(shù)據(jù)局待,而用戶不斷發(fā)起請求斑响,特別大不存在的數(shù)據(jù)菱属。這時的用戶很可能是攻擊者,攻擊會導(dǎo)致數(shù)據(jù)庫壓力過大舰罚。
解決方案:
1.在服務(wù)器端纽门,接收參數(shù)時業(yè)務(wù)接口中過濾不合法的值,null沸停,負(fù)值膜毁,和空值進行檢測和空值昭卓。
2.bloom filter:類似于哈希表的一種算法愤钾,用所有可能的查詢條件生成一個bitmap,在進行數(shù)據(jù)庫查詢之前會使用這個bitmap進行過濾候醒,如果不在其中則直接過濾能颁,從而減輕數(shù)據(jù)庫層面的壓力。
3.空值緩存:一種比較簡單的解決辦法倒淫,在第一次查詢完不存在的數(shù)據(jù)后伙菊,將該key與對應(yīng)的空值也放入緩存中,只不過設(shè)定為較短的失效時間敌土,例如幾分鐘镜硕,這樣則可以應(yīng)對短時間的大量的該key攻擊,設(shè)置為較短的失效時間是因為該值可能業(yè)務(wù)無關(guān)返干,存在意義不大兴枯,且該次的查詢也未必是攻擊者發(fā)起,無過久存儲的必要矩欠,故可以早點失效财剖。
緩存雪崩
因為緩存服務(wù)掛掉或者熱點緩存失效,所有請求都去查數(shù)據(jù)庫癌淮,導(dǎo)致數(shù)據(jù)庫連接不夠或者數(shù)據(jù)庫處理不過來躺坟,從而導(dǎo)致整個系統(tǒng)不可用。
解決方案:
加鎖排隊乳蓄、 設(shè)置過期標(biāo)志更新緩存 咪橙、 設(shè)置過期標(biāo)志更新緩存 、二級緩存(引入一致性問題)虚倒、 預(yù)熱美侦、 緩存與服務(wù)降級。
1.線程互斥:只讓一個線程構(gòu)建緩存裹刮,其他線程等待構(gòu)建緩存的線程執(zhí)行完音榜,重新從緩存獲取數(shù)據(jù)才可以,每個時刻只有一個線程在執(zhí)行請求捧弃,減輕了db的壓力赠叼,但缺點也很明顯擦囊,降低了系統(tǒng)的qps。
2.交錯失效時間:這種方法時間比較簡單粗暴嘴办,既然在同一時間失效會造成請求過多雪崩瞬场,那我們錯開不同的失效時間即可從一定長度上避免這種問題,在緩存進行失效時間設(shè)置的時候涧郊,從某個適當(dāng)?shù)闹涤蛑须S機一個時間作為失效時間即可贯被。
緩存擊穿
緩存擊穿實際上是緩存雪崩的一個特例,緩存擊穿是指緩存中沒有但數(shù)據(jù)庫中有的數(shù)據(jù)(一般是緩存時間到期)妆艘,這時由于并發(fā)用戶特別多彤灶,同時讀緩存沒讀到數(shù)據(jù),又同時去數(shù)據(jù)庫去取數(shù)據(jù)批旺,引起數(shù)據(jù)庫壓力瞬間增大幌陕,造成過大壓力。擊穿與雪崩的區(qū)別即在于擊穿是對于某一特定的熱點數(shù)據(jù)來說汽煮,而雪崩是全部數(shù)據(jù)搏熄。
解決方案:
1.緩存設(shè)置不過期。
從redis上看暇赤,確實沒有設(shè)置過期時間心例,這就保證了,不會出現(xiàn)熱點key過期問題鞋囊,也就是物理不過期止后。但是它會遇到一個數(shù)據(jù)更新的問題,或者說數(shù)據(jù)不一致的問題失暴。
在value中存儲過期時間坯门,在編碼處理的時候,有條件(過期時間小于一分鐘)對緩存數(shù)據(jù)進行更新逗扒,這個方案對性能最佳古戴。
2.使用鎖工具(分布式鎖)
$redis->setnx($key,time()+$expire);
# 加鎖
$redis->del($key);
# 解鎖
#新版本加鎖
#NX意思為SET IF NOT EXIST,即當(dāng)key不存在時矩肩,我們進行set操作现恼;
#若key已經(jīng)存在,則不做任何操作黍檩;
#PX意思是給這個key加一個過期設(shè)置
$redis->set($resource, $token, ['NX', 'PX' => 10 ]);
總結(jié):緩存好比防彈衣叉袍,不意味著你穿上防彈衣就可以刀槍不入,只有更好的使用緩存才會達到更好的作用刽酱,方案有很多喳逛,適合你的就是好的。