緩存穿透是指查詢一個一定不存在的數據,由于緩存是不命中時需要從數據庫查詢,查不到數據則不寫入緩存,這將導致這個不存在的數據每次請求都要到數據庫去查詢,進而給數據庫帶來壓力。在高并發場景下,如果某個key被高并發訪問且沒有被命中,出于對容錯性的考慮,系統會嘗試從后端數據庫中獲取數據,這可能導致大量請求直接打到數據庫上。而當該key對應的數據庫本身就是空的情況下,就會導致數據庫中并發的去執行很多不必要的查詢操作,從而對數據庫造成巨大的沖擊和壓力。
緩存穿透可能由用戶偽造不存在的數據ID并頻繁請求接口導致,也可能由黑客攻擊引起。這種攻擊會導致服務器響應緩慢,影響用戶體驗。
緩存穿透帶來的危害主要有以下幾點:
- 后端存儲負載加大:由于緩存穿透導致大量請求直接穿透緩存層到達后端存儲層,后端存儲層需要處理這些額外的請求,從而增加了其負載。如果后端存儲不具備高并發處理能力,可能會導致其性能下降,甚至宕機。
- 系統性能下降:由于大量請求直接打到后端存儲層,可能導致系統整體性能下降,響應時間延長,用戶體驗變差。
- 安全風險:緩存穿透可能被惡意用戶或黑客利用,通過偽造不存在的數據ID進行頻繁請求,從而攻擊系統,導致系統癱瘓或數據泄露。
為了解決緩存穿透問題,可以采取以下幾種策略:
-
主動方案:
- 增加ID復雜度:通過提高ID的復雜性和難以預測性,減少被惡意用戶或黑客利用的可能性。
- 數據基礎格式校驗:對客戶端發送的請求進行校驗,確保數據格式的合法性,避免非法請求穿透到數據庫。
- 加強用戶權限校驗:對用戶的訪問權限進行嚴格的校驗,確保只有合法的用戶能夠訪問數據。
- 熱點參數限流:對熱點參數進行限流,防止大量請求同時穿透緩存,對數據庫造成過大壓力。
-
被動方案:
- 緩存空對象:當查詢結果為空時,將一個空對象或默認值緩存起來,并設置一個較短的TTL(Time to Live,生存時間)。當再次遇到相同的查詢時,可以直接從緩存中返回空對象或默認值,避免再次查詢數據庫。需要注意的是,這種方式可能會導致緩存中存儲大量的無效數據,占用內存空間。
- 使用布隆過濾器:布隆過濾器是一種空間效率極高的概率型數據結構,它利用位數組和哈希函數來判斷一個元素是否在一個集合中。將所有已存在的數據key放入布隆過濾器中,當新的請求到來時,先通過布隆過濾器判斷該key是否存在。如果不存在,則直接返回;如果存在,再到緩存和數據庫中進行查詢。這種方式可以有效減少不必要的數據庫查詢,提高系統性能。
- 限制分頁數量:對于需要分頁查詢的場景,可以通過限制最大分頁數來減少緩存穿透的風險。例如,可以設置最大分頁數為100頁,超過該分頁數的請求直接返回空值或錯誤提示。
需要注意的是,以上方案并非絕對完美,需要根據具體的應用場景和需求進行選擇和調整。同時,也需要對緩存和數據庫進行監控和調優,確保系統的穩定性和性能。