Redis的快取穿透 快取擊穿和快取雪崩問題

2021-10-04 17:23:11 字數 1502 閱讀 1546

快取穿透:

關注點:要查詢的資料快取中沒有,資料庫中也沒有

情景:就是在使用了快取的基礎上,去查詢乙個快取中沒有,資料庫中也沒有的空資料,也就是壓根不存在的資料

如果被人寫乙個程式去頻繁的呼叫這個查詢空資料的請求,那麼就有可能把資料庫搞崩潰

解決方案:

1)快取空物件:

第一次查詢快取中沒有,去查詢資料庫也沒有,然後我們把查詢關鍵字當做快取的key,然後對應的value用空物件代替,然後將這條資料加入到快取中,下次再來相同查詢的時候,就不再查詢資料庫了,而是去查詢快取,返回快取中的空物件

2)布隆過濾器

步驟一:啟動的時候,根據查詢關鍵字,查詢資料庫中對應關鍵字的所有資訊,新增到布隆過濾器中

步驟二:然後在查詢快取之前先去查詢布隆過濾器,先去判斷查詢的值是否存在,如果判斷為否,那麼肯定資料庫中不存在,那麼直接返回錯誤資訊或者提示資訊,就不會再去查詢快取和資料庫,相當於只是啟動時候只去查詢了一次資料庫,用於布隆過濾器中值的寫入

(當然存在誤判,但是誤判無所謂,已經削減了大量的請求,誤判少量的請求,那也是少量的去查詢資料庫)

布隆過濾器可以參考集合的概念,但是跟集合不同的地方,或者說它的底層實現是位陣列(每個位的值只有0和1,占用空間小,那麼可以儲存的就大),然後它的實現就是當你往布隆過濾器中插入乙個資料的時候,他會根據你設定的要插入的總的資料量size和容錯率fpp去計算生成的位陣列的長度和(用於計算怎麼將儲存的資料儲存到位陣列哪些陣列下標位置的)hash函式個數,然後你去查布隆過濾器中有沒有該資料的時候,它就會拿相同的hash函式去計算陣列中儲存該資料的陣列下標位置,然後去判斷是否和插入時的一樣,來判斷是否可能存在,為什麼說可能存在呢,因為存在hash碰撞導致誤判,這個誤判率和陣列長度和容錯率有直接關係(你容錯率越低,hash函式越多,陣列長度越大,那麼產生hash碰撞誤判的機率就越小,判斷是否存在的準確性就越高,但是所需的空間資源也就越多)

快取擊穿:

關注點:要查詢的資料快取中沒有,資料庫中有(併發情況下)

情景:當高併發的情況下,n多個執行緒去查詢資料,先查詢redis,正好查詢的值過了過期時間,值被清除,那麼redis查不到了,就去mysql資料庫中查,那麼n多個執行緒請求都將直接打到mysql資料庫上

解決方案:加分布式鎖

比如99個人併發去訪問查詢同乙個資料,第一步都去查詢了快取,快取中沒有,沒有命中快取,然後加分布式鎖,其中乙個訪問執行緒持有了這個鎖,然後其他執行緒阻塞,然後持有鎖的執行緒又去查詢一次快取(這個是為了釋放鎖後,其他第一次查詢快取沒有命中的阻塞的執行緒,等第乙個執行緒查詢完,寫入快取並且釋放鎖資源之後,阻塞執行緒被喚醒,然後不是去查詢資料庫,而是去查詢快取),快取中沒有,然後查詢資料庫,將查詢到的資料寫入redis快取,並且釋放鎖資源,其他阻塞執行緒被喚醒,然後去查詢快取,而不是查詢資料庫

快取雪崩:

關注點:redis中大量的值失效

情景:redis快取宕機

或者你多個值設定了同乙個過期時間,導致過期時間後,大量值失效

對應解決方案:

高可用redis集群;

設定過期時間時有差值,避免設定大量的相同的過期時間

redis快取穿透和擊穿

專案裡為了提高查詢效能,常使用redis做快取,可高併發下又出現新的問題,如快取穿透 快取擊穿。乙個存在redis的專案,一般乙個查詢請求過來首先會從快取中查詢,快取中沒有則從資料庫裡查詢。快取穿透 當某個key對應的資料在資料來源並不存在,每次針對此key的請求從快取獲取不到,請求都會到資料來源,...

Redis快取穿透,穿透擊穿,快取雪崩

乙個一定不存在快取及查詢不到的資料,由於快取是不命中時被動寫的,並且出於容錯考慮,如果從儲存層查不到資料則不寫入快取,這將導致這個不存在的資料每次請求都要到儲存層去查詢,失去了快取的意義。有很多種方法可以有效地解決快取穿透問題,最常見的則是採用布隆過濾器,將所有可能存在的資料雜湊到乙個足夠大的bit...

Redis 快取穿透 快取擊穿 快取雪崩

快取穿透是指快取和資料庫中都沒有的資料,而使用者不斷發起請求,如發起為id為小於0的資料或id為特別大等不存在的資料。這時的使用者很可能是攻擊者,攻擊會導致資料庫壓力過大。舉例 通過分類id查詢廣告集合 param categoryid 廣告分類id return 廣告集合 public listf...