在談論快取擊穿之前,我們先來回憶下從快取中載入資料的邏輯,如下圖所示
因此,如果黑客每次故意查詢乙個在快取內必然不存在的資料,導致每次請求都要去儲存層去查詢,這樣快取就失去了意義。如果在大流量下資料庫可能掛掉。這就是快取擊穿。
場景如下圖所示:
我們正常人在登入首頁的時候,都是根據userid來命中資料,然而黑客的目的是破壞你的系統,黑客可以隨機生成一堆userid,然後將這些請求懟到你的伺服器上,這些請求在快取中不存在,就會穿過快取,直接懟到資料庫上,從而造成資料庫連線異常。
在這裡我們給出三套解決方案,大家根據專案中的實際情況,選擇使用.
講下述三種方案前,我們先回憶下redis的setnx方法
setnx key value
將 key 的值設為 value ,當且僅當 key 不存在。
若給定的 key 已經存在,則 setnx 不做任何動作。
setnx 是『set if not exists』(如果不存在,則 set)的簡寫。
可用版本:>= 1.0.0
時間複雜度: o(1)
返回值: 設定成功,返回 1。設定失敗,返回 0 。
效果如下
redis> exists job # job 不存在1、使用互斥鎖(integer) 0
redis> setnx job "programmer" # job 設定成功
(integer) 1
redis> setnx job "code-farmer" # 嘗試覆蓋 job ,失敗
(integer) 0
redis> get job # 沒有被覆蓋
"programmer"
該方法是比較普遍的做法,即,在根據key獲得的value值為空時,先鎖上,再從資料庫載入,載入完畢,釋放鎖。若其他執行緒發現獲取鎖失敗,則睡眠50ms後重試。
至於鎖的型別,單機環境用並發包的lock型別就行,集群環境則使用分布式鎖( redis的setnx)
集群環境的redis的**如下所示:
stringget(stringkey)elseelseelseelse{優點思路簡單value = db.get(key);
redis.set(key, value);
returnvalue;
保證一致性
效能強缺點
**複雜度增大
需要另外維護乙個集合來存放快取的key
布隆過濾器不支援刪值操作
redis快取擊穿
1 快取擊穿出現的場景 我們知道redis的資料是儲存在記憶體的,而記憶體是有限的,所以一般會設定過期時間,當某個key過期了,而此時大量的併發來請求這個key,導致都去請求mysql啦,而mysql的併發連線數很低,缺少了redis這層盾牌,mysql自然扛不住,這不是架構的問題,因為之前的架構中...
Redis快取擊穿
什麼是快取擊穿 key對應的資料存在,但是在redis中key過期了,此時如有大量的併發請求過來,這些請求發現快取過期一般都會從後端伺服器載入資料並回設到快取,這個時候大併發請求可能會瞬間把後端db壓垮 如圖 出現快取穿透的特點 1.資料庫訪問壓力瞬間增加 2.redis裡面出現大量key過期 3....
redis 快取擊穿 3
在談論快取擊穿之前,我們先來回憶下從快取中載入資料的邏輯,如下圖所示 因此,如果黑客每次故意查詢乙個在快取內必然不存在的資料,導致每次請求都要去儲存層去查詢,這樣快取就失去了意義。如果在大流量下資料庫可能掛掉。這就是快取擊穿。場景如下圖所示 我們正常人在登入首頁的時候,都是根據userid來命中資料...