缓存穿透,瞬间并发,缓存雪崩的解决方法
一.緩存穿透:
?????緩存穿透是指查詢一個一定不存在的數據,由于緩存是不命中時需要從數據庫查詢,查不到數據則不寫入緩存,這將導致這個不存在的數據每次請求都要到數據庫去查詢,造成緩存穿透。
?????解決辦法:
?????1.布隆過濾
??對所有可能查詢的參數以hash形式存儲,在控制層先進行校驗,不符合則丟棄。還有最常見的則是采用布隆過濾器,將所有可能存在的數據哈希到一個足夠大的bitmap中,一個一定不存在的數據會被這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力。
??補充:
??????Bloom filter
??適用范圍:可以用來實現數據字典,進行數據的判重,或者集合求交集
??基本原理及要點:對于原理來說很簡單,位數組+k個獨立hash函數。將hash函數對應的值的位數組置1,查找時如果發現所有hash函數對應位都是1說明存在,很明顯這個過程并不保證查找的結果是100%正確的。同時也不支持刪除一個已經插入的關鍵字,因為該關鍵字對應的位會牽動到其他的關鍵字。所以一個簡單的改進就是counting Bloom filter,用一個counter數組代替位數組,就可以支持刪除了。添加時增加計數器,刪除時減少計數器。
?????2. 緩存空對象. 將 null 變成一個值.
??也可以采用一個更為簡單粗暴的方法,如果一個查詢返回的數據為空(不管是數 據不存在,還是系統故障),我們仍然把這個空結果進行緩存,但它的過期時間會很短,最長不超過五分鐘。
?緩存空對象會有兩個問題:
?第一,空值做了緩存,意味著緩存層中存了更多的鍵,需要更多的內存空間 ( 如果是攻擊,問題更嚴重 ),比較有效的方法是針對這類數據設置一個較短的過期時間,讓其自動剔除。
?第二,緩存層和存儲層的數據會有一段時間窗口的不一致,可能會對業務有一定影響。例如過期時間設置為 5分鐘,如果此時存儲層添加了這個數據,那此段時間就會出現緩存層和存儲層數據的不一致,此時可以利用消息系統或者其他方式清除掉緩存層中的空對象。
?
?
二.緩存雪崩
????如果緩存集中在一段時間內失效,發生大量的緩存穿透,所有的查詢都落在數據庫上,造成了緩存雪崩。
????這個沒有完美解決辦法,但可以分析用戶行為,盡量讓失效時間點均勻分布。大多數系統設計者考慮用加鎖或者隊列的方式保證緩存的單線程(進程)寫,從而避免失效時大量的并發請求落到底層存儲系統上。
?
????解決方法
???1. 加鎖排隊. 限流-- 限流算法. 1.計數 2.滑動窗口 3.??令牌桶Token Bucket 4.漏桶 leaky bucket [1]
?在緩存失效后,通過加鎖或者隊列來控制讀數據庫寫緩存的線程數量。比如對某個key只允許一個線程查詢數據和寫緩存,其他線程等待。
?業界比較常用的做法,是使用mutex。簡單地來說,就是在緩存失效的時候(判斷拿出來的值為空),不是立即去load db,而是先使用緩存工具的某些帶成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一個mutex key,當操作返回成功時,再進行load db的操作并回設緩存;否則,就重試整個get緩存的方法。
SETNX,是「SET if Not eXists」的縮寫,也就是只有不存在的時候才設置,可以利用它來實現鎖的效果。
?
?????2.數據預熱
??可以通過緩存reload機制,預先去更新緩存,再即將發生大并發訪問前手動觸發加載緩存不同的key,設置不同的過期時間,讓緩存失效的時間點盡量均勻
?
?????3.做二級緩存,或者雙緩存策略。
?????A1為原始緩存,A2為拷貝緩存,A1失效時,可以訪問A2,A1緩存失效時間設置為短期,A2設置為長期。
?
??????4.緩存永遠不過期
?這里的“永遠不過期”包含兩層意思:
????(1) 從緩存上看,確實沒有設置過期時間,這就保證了,不會出現熱點key過期問題,也就是“物理”不過期。
?????(2) 從功能上看,如果不過期,那不就成靜態的了嗎?所以我們把過期時間存在key對應的value里,如果發現要過期了,通過一個后臺的異步線程進行緩存的構建,也就是“邏輯”過期.
?從實戰看,這種方法對于性能非常友好,唯一不足的就是構建緩存時候,其余線程(非構建緩存的線程)可能訪問的是老數據,但是對于一般的互聯網功能來說這個還是可以忍受。
版權聲明:本文為博主原創文章,未經博主允許不得轉載?
[1] 接口限流算法總結 含代碼 http://blog.csdn.net/zxp_cpinfo/article/details/70103114?locationNum=3&fps=1?
?
總結
以上是生活随笔為你收集整理的缓存穿透,瞬间并发,缓存雪崩的解决方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 缓存穿透、缓存雪崩、redis并发
- 下一篇: TCP的状态转换及生产问题实操