當查詢redis中沒有的數據時,該查詢會下沉到數據庫層,同時數據庫層也沒有該數據,當這種情況大量出現或被惡意攻擊時,接口的訪問全部透過Redis訪問數據庫,而數據庫中也沒有這些數據,我們稱這種現象為"緩存穿透"。緩存穿透會穿透Redis的保護,提升底層數據庫的負載壓力,同時這類穿透查詢沒有數據返回也造成了網絡和計算資源的浪費。
解決方案:
- 在接口訪問層對用戶做校驗,如接口傳參、登陸狀態、n秒內訪問接口的次數;
- 利用布隆過濾器,將數據庫層有的數據key存儲在位數組中,以判斷訪問的key在底層數據庫中是否存在;
第一種解決方案很好理解,這里介紹一下第二種方案,在前一篇文章中我們介紹了Redis的布隆過濾器,我們知道布隆過濾器可以判斷key一定不在集合內以及key極有可能在集合內。
基于布隆過濾器,我們可以先將數據庫中數據的key存儲在布隆過濾器的位數組中,每次客戶端查詢數據時先訪問Redis:
- 如果Redis內不存在該數據,則通過布隆過濾器判斷數據是否在底層數據庫內;
- 如果布隆過濾器告訴我們該key在底層庫內不存在,則直接返回null給客戶端即可,避免了查詢底層數據庫的動作;
- 如果布隆過濾器告訴我們該key極有可能在底層數據庫內存在,那么將查詢下推到底層數據庫即可;
布隆過濾器有誤判率,雖然不能完全避免數據穿透的現象,但已經可以將99.99%的穿透查詢給屏蔽在Redis層了,極大的降低了底層數據庫的壓力,減少了資源浪費。