緩存系統設計:緩存擊穿,緩存雪崩,緩存穿透,緩存預熱


緩存擊穿

假設一個緩存系統中存在一個熱Key,每分每秒都有大量的請求訪問這個key,那么當這個熱key因為過期而失效,一瞬間所有的請求直接打到DB上,這種場景稱做緩存擊穿。

 

為了避免這種問題業界一般有如下解決方案

1.互斥鎖

當緩存過期時,常見的邏輯是直接請求DB,然后再set回緩存中。為了避免緩存擊穿的問題,可以在請求DB的地方加一個鎖(如果是分布式系統就需要使用分布式鎖),爭取到鎖的就去訪問DB,沒爭取到的就阻塞一段時間再請求緩存,減少直接打到DB的請求。

2.永不過期

不給key設置有效期,讓key永不過期,然后以定時任務的形式,主動去更新緩存。

3.邏輯過期

同樣不給key設置有效期,而是將expired值作為緩存數據的一個字段放入緩存中,取出來時校驗一下是否過期,如果過期了則重新設置有效期,並起一個異步線程去更新這緩存。

 

緩存雪崩

假設一個緩存系統中,大量的key用的都是同一個expired值,那么在某一瞬間,這些key可能會集體全部失效,所有的請求直接打到DB上,這種場景稱作緩存雪崩

如何解決?

1.隨機過期時間

將數據寫入緩存時往往會設置一個expired值,為了避免在某一時間統統全部過期,可以在expired值的基礎上加上1~5min的隨機值,避免這種情況。這樣緩存就不會在某一瞬間突然全部過期了。

 

緩存穿透

當用戶訪問一個不存在的key時,緩存取不到,按邏輯就是從庫里面取,這種請求一多,打到DB的請求也就增加了,這種場景稱作緩存擊穿。

如下,用戶不斷請求用戶信息,但ID都為無效的負數,緩存里面沒有,所有請求可能直接打到DB上,如果是惡意請求的話,危害頗大。

GET /user/-1

GET /user/-2

....

GET /user/-3

1.緩存不存在的值

如果查詢到一個空的結果時,可以仍然將這個空的結果進行緩存,下次在請求的話就會這就返回這個空的結果而不是請求DB。當然,如果這種請求一多,存儲里就會存儲大量這種無效值,對緩存的空間也是一種壓力,所以推薦使用下面BloomFilter的方式。

2.BloomFilter

BloomFilter的特性就是當BloomFilter認為有數據時,是可能有,當認為沒有數據時,那就是真沒有。故可以利用BloomFilter的特性,擋掉這些不存在的請求。

 

緩存預熱 

系統剛啟動,緩存還未完全構建,但是用戶不會管這么多,直接一股腦的訪問過來,請求又直接打到DB了。如果遇到這種場景,可以利用緩存預熱的思想,在系統啟動時調用一個后台接口,構建一遍緩存。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM