快收藏!一個技巧從此不再搞混緩存穿透和緩存擊穿
在 Redis 中有兩個定義:一個緩存擊穿、一個緩存穿透,因為二者的名字比較像,因此很容易就搞混了。但本文會給你提供一個記憶的小技巧,幫你徹底區(qū)分二者的定義。
在講這個技巧之前,我們先來了解一下二者的區(qū)別。
1.定義與區(qū)別
- 緩存穿透(Cache Penetration):緩存穿透是指查詢的數(shù)據(jù)既不在緩存中,也不在數(shù)據(jù)庫中,但用戶仍然頻繁請求該數(shù)據(jù),導致請求直接穿透到數(shù)據(jù)庫,增加數(shù)據(jù)庫壓力。
a.核心問題:請求的數(shù)據(jù)根本不存在,但請求量很大,導致數(shù)據(jù)庫被無效查詢。
- 緩存擊穿(Cache Breakdown):緩存擊穿是指 熱點數(shù)據(jù)的緩存失效,大量并發(fā)請求同時查詢該數(shù)據(jù),導致請求直接沖擊數(shù)據(jù)庫,增加數(shù)據(jù)庫壓力。
a.核心問題:緩存中的數(shù)據(jù)失效,但數(shù)據(jù)庫中有對應的數(shù)據(jù),請求量集中導致數(shù)據(jù)庫壓力驟增。
2.常見場景
- 緩存穿透:
a.用戶請求不存在的 ID(如負數(shù) ID 或非法字符)。
b.惡意攻擊者故意請求不存在的數(shù)據(jù)。
c.示例:請求用戶 ID 為 -1 或不存在的用戶信息。
- 緩存擊穿:
a.熱點數(shù)據(jù)(如熱門商品信息、熱門新聞)的緩存過期。
b.大量用戶同時請求該熱點數(shù)據(jù)。
c.示例:促銷活動中的熱門商品信息突然失效。
3. 解決方案
(1)緩存穿透的解決方案
布隆過濾器(Bloom Filter):在緩存層前加一層布隆過濾器,預存所有合法 Key 的哈希值。請求到達時,先檢查布隆過濾器:
- 如果不存在,直接攔截請求,返回空。
- 如果存在,再查詢緩存或數(shù)據(jù)庫。
- 優(yōu)點:內(nèi)存占用少,能有效攔截不存在的請求。
- 缺點:可能存在誤判,需要合理設置參數(shù)。
緩存空值(Cache Null):對查詢結(jié)果為空的 Key,緩存一個 Null 值,避免重復穿透。
- 優(yōu)點:實現(xiàn)簡單,能有效減少數(shù)據(jù)庫壓力。
- 缺點:可能會占用額外的緩存空間。
參數(shù)校驗:在查詢緩存之前,先對請求的參數(shù)進行合法性檢查,如過濾非法字符、判斷參數(shù)范圍等,對于明顯錯誤的參數(shù),直接攔截返回。
(2)緩存擊穿的解決方案
互斥鎖(Mutex Lock):當緩存失效時,通過分布式鎖讓一個線程重建緩存,其他線程等待鎖釋放后重試。
- 優(yōu)點:能有效避免多個線程同時查詢數(shù)據(jù)庫。
- 缺點:實現(xiàn)復雜,可能會影響性能。
永不過期(Logical Expiration):對熱點 Key 設置物理永不過期,通過后臺異步線程定期更新緩存,保證數(shù)據(jù)新鮮度。
- 優(yōu)點:避免緩存失效導致的數(shù)據(jù)庫壓力。
- 缺點:需要額外的邏輯來管理緩存更新。
熔斷降級:在緩存失效期間,啟用降級策略(如返回默認值或靜態(tài)頁面),保護數(shù)據(jù)庫。
- 優(yōu)點:能有效緩解數(shù)據(jù)庫壓力。
- 缺點:用戶體驗可能受影響。
4.對比
問題 | 定義 | 常見場景 | 解決方案 |
緩存穿透 | 請求的數(shù)據(jù)既不在緩存中,也不在數(shù)據(jù)庫中,但請求量很大,導致數(shù)據(jù)庫壓力增大 | 非法請求、惡意攻擊 | 布隆過濾器、緩存空值、參數(shù)校驗 |
緩存擊穿 | 熱點數(shù)據(jù)的緩存失效,大量并發(fā)請求直接沖擊數(shù)據(jù)庫 | 熱點數(shù)據(jù)失效、高并發(fā)場景 | 互斥鎖、永不過期、熔斷降級 |
通過理解它們的定義、場景和解決方案,你可以更清晰地區(qū)分緩存穿透和緩存擊穿,并在實際開發(fā)中選擇合適的解決方法。
5.記憶秘訣
- 緩存擊穿:核心是熱點數(shù)據(jù)失效 -> 解決方案是重建熱點數(shù)據(jù)。
- 緩存穿透:核心是 Redis 和 MySQL 都沒有數(shù)據(jù) -> 解決方案是攔截無效請求。
因此,我們可以認為:
- 緩存擊穿 -> 正常的數(shù)據(jù)失效引發(fā)的問題。
- 緩存穿透 -> 非正常的數(shù)據(jù)訪問引發(fā)的問題。
就像警察叔叔審訊犯人一樣,我們可以用“擊穿犯罪嫌疑人的心里防線”,但不能用“穿透犯罪嫌疑的心里防線”,所以,擊穿是“正義之詞”,而穿透是“非正義之詞”,例如,你這點小心思,我還看不“透”,“透”這個詞通常是用來描述不好的事情的,因此我們可以使用這個技巧來徹底區(qū)分緩存擊穿和緩存穿透了,如下圖所示:
小結(jié)
緩存擊穿和緩存穿透是 Redis 中兩個常見的高頻面試問題,但又很容易搞混二者的定義,我們通過學習本文的內(nèi)容,相信可以徹底的區(qū)分二者的定義。