前言
在今天的互聯網里,高並發
、大數據量
、大流量
已經成為了代言詞,那么我們的系統
也承受着巨大的壓力
,首當其沖的解決方案就是redis
。
那么redis使用不當就會產生雪崩
、穿透
、擊穿
等問題,這也是考驗一個程序員技術能力
的時刻。
當然面試的時候,這也是高頻面試題
,幾乎大廠都會問到。下面跟着貼心老哥
一起來看看這些技術吧。
緩存雪崩

舉例
雙十一期間,所有用戶一打開淘寶就是進入首頁
,首頁的壓力非常大,為了提高並發,將網站首頁數據
都緩存到redis
里,所有的redis key失效時間
都是3小時
。
雙十一當天大量用戶剁手狂歡
,這時候3個小時過去了,redis里首頁的key緩存全部失效
,這時候redis里查詢不到數據了,只能去數據庫
中查詢,造成數據庫無法響應掛掉
。
用戶進不去首頁沒法剁手了,馬爸爸
就不開心
了,把這個程序員外派到非洲
了。

一句話總結
在高並發
下,大量緩存key在同一時間失效
,大量請求直接落在數據庫上,導致數據庫宕機。
解決方案
- 隨機設置key失效時間,避免大量key集體失效。
setRedis(Key,value,time + Math.random() * 10000); 復制代碼
-
若是集群部署,可將熱點數據均勻分布在不同的Redis庫中也能夠避免key全部失效問題
-
不設置過期時間
-
跑定時任務,在緩存失效前刷進新的緩存
緩存穿透

舉例
老哥做了一個網站火了
,動了別人的蛋糕,於是開始瘋狂攻擊
老哥的網站,由於老哥網絡安全
方面學藝不精被人鑽了空子。
某人用腳本瘋狂的給老哥發送請求,查詢 id = -1
的數據,redis並沒有這樣的數據,這時候就穿透redis
,直接打到了數據庫
上。
半夜老哥在睡覺並沒有察覺,他瘋狂攻擊老哥一晚上,結果把數據庫
搞掛了,然后老哥的網站
也掛了。
一句話總結
redis緩存
和數據庫
中沒有相關數據(例用戶直接攜帶id<=0
的參數不斷發起請求),redis中沒有這樣的數據,無法進行攔截
,直接被穿透到數據庫
,導致數據庫壓力過大宕機。
解決方案
-
對不存在的數據緩存到redis中,設置key,value值為null(不管是數據未null還是系統bug問題),並設置一個短期過期時間段,避免過期時間過長影響正常用戶使用。
-
拉黑該IP地址
-
對參數進行校驗,不合法參數進行攔截
-
布隆過濾器 將所有可能存在的數據哈希到一個足夠大的bitmap(位圖)中,一個一定不存在的數據會被 這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力。
緩存擊穿

舉例
雙十一馬爸爸
突發奇想,想拍賣
自己穿了20年的老布鞋
,並且附帶本人簽名,程序員將該鞋的信息存到了redis中,設置了3小時
過期。尋思3小時夠他們搶了吧,但他低估了馬爸爸的魅力。
該商品引起了一千萬人關注,這些人不斷的競拍這雙鞋,價格越拍越高,馬爸爸樂開了花。
競拍了2小時59
分,馬上要拍到一個億了,突然這雙鞋在redis里的key數據過期了
,導致該key的大量請求,都打到了數據庫,直接導致數據庫掛掉了,服務無法響應。
競拍到此結束,鞋沒賣出去,馬爸爸又不開心了,把這個程序員也外派到非洲
了。

一句話總結
某一個
熱點key,在不停地扛着高並發,當這個熱點key在失效的一瞬間
,持續的高並發訪問就擊破緩存
直接訪問數據庫,導致數據庫宕機。
解決方案
-
設置熱點數據"永不過期"
-
加上互斥鎖:上面的現象是多個線程同時去查詢數據庫的這條數據,那么我們可以在第一個查詢數據的請求上使用一個互斥鎖來鎖住它
其他的線程走到這一步拿不到鎖就等着,等第一個線程查詢到了數據,然后將數據放到redis緩存起來。后面的線程進來發現已經有緩存了,就直接走緩存
最后總結
雪崩是大面積
的key緩存失效;穿透是redis里不存在
這個緩存key;擊穿是redis某一個熱點
key突然失效,最終的受害者都是數據庫。
思考
未雨綢繆
:將redis、MySQL等搭建成高可用的集群,防止單點。
亡羊補牢
:服務中進行限流 + 降級,防止MySQL被打崩潰。
重振旗鼓
:Redis 持久化 RDB+AOF,宕機重啟,自動從磁盤上加載數據,快速恢復緩存數據。