1、資料的查詢過程:
程式在處理使用者請求時候,一般先查詢快取中是否存在使用者的查詢資料,如果快取中不存在再去查詢資料庫,如果在資料庫中查詢到了資料,在把資料返回給使用者同時把資料放入快取中;如果在資料庫中也沒有查詢到資料,則返回空值並且沒有資料放入到快取中。當使用者的大量的資料請求都不在快取中時,會對資料庫造成較大壓力,尤其是有惡意使用者發起惡意攻擊時。
2、快取穿透
(1)what
查詢乙個一定不存在的資料值,由於快取不命中所以需要從資料庫查詢,資料庫中查不到資料則不寫入快取,這將導致這個不存在的資料每次請求都要到資料庫去查詢,失去了快取的意義,造成快取穿透。(
查詢的是一定不存在的資料,所以快取中查不到,所以一定會去訪問資料庫,失去了快取減緩資料庫訪問壓力的作用)
(2)解決方
a、將可能出現的快取key的組合方式的所有數值以hash形式儲存在乙個很大的bitmap中《布隆過濾器》(需要考慮如何將這個可能出現的資料的hash值之後同步到bitmap中, eg. 後端每次新增乙個可能的組合就同步一次,或者 窮舉),乙個一定不存在的資料會被這個bitmap攔截掉,從而避免了對底層儲存系統的查詢壓力
b、常用: 如果對應在資料庫中的資料都不存在,我們將此key對應的value設定為乙個預設的值,比如「null」,並設定乙個快取的失效時間。當然這個key的時效比正常的時效要小的多
3、快取擊穿
(1)what
與快取穿透不同,快取擊穿中的熱點key在資料庫中是存在的,在快取中也存在過,只是在這些熱點資料失效的瞬間,發起了大量對熱點資料的請求,導致快取中不命中直接訪問資料庫,造成對資料庫的巨大壓力。
(2)解決方案
a、通過synchronized+雙重檢查機制:某個key只讓乙個執行緒查詢,阻塞其它執行緒在同步塊中,繼續判斷檢查,保證不存在,才去查db
b、設定value永不過期,這種方式可以說是最可靠的,最安全的但是佔空間,記憶體消耗大,並且不能保持資料最新 這個需要根據具體的業務邏輯來做
c、使用互斥鎖(mutex key),業界比較常用的做法,是使用mutex。簡單地來說,就是在快取失效的時候(判斷拿出來的值為空),不是立即去load db,而是先使用快取工具的某些帶成功操作返回值的操作(比如redis的setnx或者memcache的add)去set乙個mutex key,當操作返回成功時,再進行load db的操作並回設快取;否則,就重試整個get快取的方法。setnx,是「set if not exists」的縮寫,也就是只有不存在的時候才設定,可以利用它來實現鎖的效果。
4、快取雪崩
(1)what
redis伺服器掛掉,多個key查詢並且出現高併發,快取中失效或者查不到,然後都去db查詢,導致請求大量湧至資料庫,使得db壓力突然飆公升,從而崩潰。
(2)解決方案
a、在快取失效後,通過加鎖或者佇列來控制讀資料庫寫快取的執行緒數量。比如對某個key只允許乙個執行緒查詢資料和寫快取,其他執行緒等待。(跟擊穿的第乙個方案類似,但是這樣是避免不了其它key去查資料庫,只能減少查詢的次數)
b、可以通過快取reload機制,預先去更新快取,再即將發生大併發訪問前手動觸發載入快取
不同的key,設定不同的過期時間,具體值可以根據業務決定,讓快取失效的時間點盡量均勻
c、做二級快取,或者雙快取策略。a1為原始快取,a2為拷貝快取,a1失效時,可以訪問a2,a1快取失效時間設定為短期,a2設定為長期。(這種方式複雜點)
redis快取穿透和擊穿
專案裡為了提高查詢效能,常使用redis做快取,可高併發下又出現新的問題,如快取穿透 快取擊穿。乙個存在redis的專案,一般乙個查詢請求過來首先會從快取中查詢,快取中沒有則從資料庫裡查詢。快取穿透 當某個key對應的資料在資料來源並不存在,每次針對此key的請求從快取獲取不到,請求都會到資料來源,...
Redis快取穿透,穿透擊穿,快取雪崩
乙個一定不存在快取及查詢不到的資料,由於快取是不命中時被動寫的,並且出於容錯考慮,如果從儲存層查不到資料則不寫入快取,這將導致這個不存在的資料每次請求都要到儲存層去查詢,失去了快取的意義。有很多種方法可以有效地解決快取穿透問題,最常見的則是採用布隆過濾器,將所有可能存在的資料雜湊到乙個足夠大的bit...
Redis 快取穿透 快取擊穿 快取雪崩
快取穿透是指快取和資料庫中都沒有的資料,而使用者不斷發起請求,如發起為id為小於0的資料或id為特別大等不存在的資料。這時的使用者很可能是攻擊者,攻擊會導致資料庫壓力過大。舉例 通過分類id查詢廣告集合 param categoryid 廣告分類id return 廣告集合 public listf...