緩存穿透、緩存雪崩、緩存擊穿的原因及解決方案
- 緩存穿透
是指查詢一個一定不存在的數據,這將導致這個不存在的數據每次請求都要DB去查詢,失去了緩存的一樣。在流量大的時候,可能DB就掛了。
解決方案
有很多種方法可以有效地解決緩存穿透問題:
1.對空值做緩存;
2.設置key的規則;
3.采用布隆過濾器,將所有可能存在的數據哈希到一個足夠大的bitmap中,一個一定不存在的數據會被這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力。
- 緩存雪崩
是指我們設置緩存時采用了相同的過期時間,導致緩存在某一時間同時失效,請求全部到DB,DB瞬時壓力過重雪崩。
解決方案
可以設置一個失效時間的隨機數,這樣可以讓緩存的過期時間重復率降低,從而導致雪崩。
- 緩存擊穿
我們設置了過期時間的key,如果這些key可能在某些時間點被超高並發地訪問,恰好在這個時間點某個key緩存過期,有大量的並發請求過來,這些請求發現緩存過期就會從后端DB加載數據並重新set到緩存中,這個時間大並發的請求可能會瞬間把后端DB壓垮。
解決方案
我們的目標是:盡量少的線程去查詢數據重新set到緩存中並且要滿足數據一致性;
1.使用互斥鎖:
實現方式如下:
public void get(String key) { String value = jedis.get(key); if (value == null) { if (jedis.setnx(key_nx, "1")) { jedis.expire(key_nx, 3 * 60); value = db.get(key); jedis.set(key, value); jedis.delete(key_nx); } else { //其他線程休息50毫秒后重試 Thread.sleep(50); get(key); } } }