前言
在今天的互聯網里,高并發、大資料量、大流量已經成為了代言詞,那么我們的系統也承受著巨大的壓力,首當其沖的解決方案就是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,宕機重啟,自動從磁盤上加載資料,快速恢復快取資料,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/243457.html
標籤:Java
