Redis 緩存問題
緩存穿透
緩存穿透問題描述
緩存穿透是指查詢一個一定不存在的數(shù)據(jù),由于緩存是不命中時被動寫的,并且出于容錯考慮,如果從DB查不到數(shù)據(jù)則不寫入緩存,這將導致這個不存在的數(shù)據(jù)每次都要到DB去查詢,失去了緩存的意義。在流量大時,DB可能會掛掉,黑客可以利用不存在的key頻繁攻擊我們的應用。
緩存穿透解決方案
- 采用布隆過濾器,將所有可能存在的數(shù)據(jù)key哈希到一個足夠大的bitmap中,一個一定不存在的數(shù)據(jù)key會被這個bitmap攔截掉,避免對底層DB系統(tǒng)的查詢壓力。
- 如果一個key在DB中查詢?yōu)榭諘r,仍然把這個空結果進行緩存,過期時間設置很短,不超過五分鐘。
緩存雪崩
緩存雪崩問題描述
緩存雪崩是指在我們設置緩存時采用了相同的過期時間,導致大量緩存在某一時刻同時失效,請求全部轉發(fā)到DB,DB瞬時壓力過重發(fā)生雪崩效應。
緩存雪崩解決方案
- 寫緩存時考慮采用加鎖或者隊列的方式保證緩存的單線程寫,避免大量緩存key同時失效。
- 緩存過期時間分散開,可以在原有的緩存失效時間基礎上增加一個隨機時間,這樣每個緩存key的過期時間重復率會很低。
- 緩存key不設置過期時間,可以在緩存值中保存過期時間字段。
緩存擊穿
緩存擊穿問題描述
對于一些設置了過期時間的緩存key,如果這些key在某個時間點被超高并發(fā)訪問,是一種非常熱點的數(shù)據(jù)。和緩存雪崩的區(qū)別是針對某一個key緩存,緩存雪崩是多個key。
熱點緩存key在某個時間點過期的時候,恰好這個時間點有大量并發(fā)請求這個緩存key,這些請求發(fā)現(xiàn)緩存key已經(jīng)過期會從后端DB加載數(shù)據(jù)并回填緩存 ,這個大并發(fā)請求可能會瞬間把DB壓垮。
緩存擊穿解決方案
- 使用互斥鎖(mutex key),就是在緩存失效的時候(根據(jù)緩存key查詢緩存為null),不是立即去查詢DB,而是先去獲取鎖(JVM鎖或分布式鎖都可以),只有成功獲取鎖的線程去查詢DB然后回填緩存,通過鎖保證只有一個線程去查詢DB,從而減小DB壓力,當緩存回填成功后,其他線程再去查詢緩存即可。
- 提前使用互斥鎖,在value內(nèi)部設置緩存過期時間,每次查詢緩存時判斷緩存是否即將過期,如果超過一定閾值,可以提前觸發(fā)查詢數(shù)據(jù)庫更新緩存操作,查詢數(shù)據(jù)庫更新緩存操作同樣需要加鎖實現(xiàn)。
- 緩存不設置過期時間,這就不會出現(xiàn)熱點key過期問題,如果需要對緩存進行更新或者刪除操作,可以通過后臺異步任務方式進行緩存更新。
- 訪問數(shù)據(jù)庫增加限流功能,可以采用netflix的hystrix實現(xiàn)降級限流功能。