緩存穿透:重復查詢一條數據,redis緩存中沒有,數據庫中也沒有。就容易照成緩存擊穿。
解決方案:
1、前端做出限制,例如查詢id為-1的數據,這一條很明顯。redis中和mysql中都不可能查詢到,所以在前端或service(防止有人跳過前端,直接以ip/project?id=-1請求)做出相應攔截(攔截id<0)。
2、如查詢一次發現這種情況,可以將它緩存到redis中,但是建議5分鍾后自動銷毀(防止內存被占滿)。
3、用布隆過濾器,查詢不到的值設置為0.再次查詢就直接攔截。
緩存擊穿:某條數據緩存中沒有,數據庫中有。在同一時間,多個用戶同時查詢,造成數據庫壓力過大,嚴重情況數據庫可能直接掛掉。
解決方案:
1、添加互斥鎖:
- ReentrantLock公平鎖
- 根據key值加鎖,這樣線程之間會不影響,不會因為某一個線程獲取了鎖,其它線程就處於等待時間,也就是線程A從數據庫取key1的數據並不妨礙線程B取key2的數據
2、設置熱點數據永不過期(物理上的不過期、"邏輯上"的不過期(緩存到期動態構建緩存))
緩存雪崩:很多條數據的過期時間到了,從而導致數據庫查詢量巨大,和緩存擊穿不同,這是多條數據同時過期。
解決方案:
1、設置熱點數據不過期
2、在緩存的過期時間末尾追加 隨機時間1-3min,盡量不能讓熱點數據同一時間失效。
3、可設置分布式緩存數據庫,將熱點數據庫分別放到不同的緩存數據庫中,避免某一點因壓力過大而down掉。
緩存與數據庫一致性:在數據庫中插入一條新的記錄之后,查詢redis。結果redis中沒有,重啟redis之后,redis中才會生效。
解決方案:
1、插入數據庫的同時,手動將該條數據插入到緩存中。
2、設置定時任務,清空redis中的數據,然后再次保存。