緩存失效###
原因:引起這個原因的主要因素是高并發(fā)下,我們一般設(shè)定一個緩存的過期時間時贩虾,可能有一些會設(shè)置5分鐘啊催烘,10分鐘這些;并發(fā)很高時可能會出在某一個時間同時生成了很多的緩存缎罢,并且過期時間在同一時刻伊群,這個時候就可能引發(fā)——當過期時間到后,這些緩存將同時失效策精。
影響:緩存同時失效時產(chǎn)生的雪崩效應(yīng)昂秃,將所有請求全部放在數(shù)據(jù)庫上童太,這樣很容易就達到數(shù)據(jù)庫的瓶頸,導致服務(wù)無法正常提供。盡量避免這種場景的發(fā)生斩祭。
解決:一個簡單方案就是將緩存失效時間分散開,不要所以緩存時間長度都設(shè)置成5分鐘或者10分鐘;比如我們可以在原有的失效時間基礎(chǔ)上增加一個隨機值,比如1-5分鐘隨機抽莱,這樣每一個緩存的過期時間的重復率就會降低,就很難引發(fā)集體失效的事件骄恶。
緩存穿透###
場景:指查詢一個一定不存在的數(shù)據(jù)食铐,由于緩存是不命中時被動寫的,并且出于容錯考慮僧鲁,如果從存儲層查不到數(shù)據(jù)則不寫入緩存虐呻,這將導致這個不存在的數(shù)據(jù)每次請求都要到存儲層去查詢,失去了緩存的意義寞秃。
影響:當在流量較大時斟叼,出現(xiàn)這樣的情況,一直請求DB春寿,很容易導致服務(wù)掛掉朗涩。
解決:
在封裝的緩存SET和GET部分增加個步驟,如果查詢一個KEY不存在绑改,就已這個KEY為前綴設(shè)定一個標識KEY谢床;以后再查詢該KEY的時候,先查詢標識KEY厘线,如果標識KEY存在识腿,就返回一個協(xié)定好的非false或者NULL值,然后APP做相應(yīng)的處理造壮,這樣緩存層就不會被穿透渡讼。當然這個驗證KEY的失效時間不能太長。
如果一個查詢返回的數(shù)據(jù)為空(不管是數(shù)據(jù)不存在费薄,還是系統(tǒng)故障)硝全,我們?nèi)匀话堰@個空結(jié)果進行緩存,但它的過期時間會很短楞抡,一般只有幾分鐘伟众。
采用布隆過濾器,將所有可能存在的數(shù)據(jù)哈希到一個足夠大的bitmap中召廷,一個一定不存在的數(shù)據(jù)會被這個bitmap攔截掉凳厢,從而避免了對底層存儲系統(tǒng)的查詢壓力。
緩存并發(fā)###
場景:當網(wǎng)站并發(fā)訪問高竞慢,一個緩存如果失效先紫,可能出現(xiàn)多個進程同時查詢DB,同時設(shè)置緩存的情況筹煮,如果并發(fā)確實很大遮精,這也可能造成DB壓力過大,還有緩存頻繁更新的問題。
解決:對緩存查詢加鎖本冲,如果KEY不存在准脂,就加鎖,然后查DB入緩存檬洞,然后解鎖狸膏;其他進程如果發(fā)現(xiàn)有鎖就等待,然后等解鎖后返回數(shù)據(jù)或者進入DB查詢添怔。