本篇部落格我們來介紹Redis使用過程中需要注意的三種問題:快取穿透、快取擊穿、快取雪崩。
1、快取穿透
一、概念
快取穿透:快取和資料庫中都沒有的資料,可使用者還是源源不斷的發起請求,導致每次請求都會到資料庫,從而壓垮資料庫。
如下圖紅色的流程:
比如客戶查詢一個根本不存在的東西,首先從Redis中查不到,然後會去資料庫中查詢,資料庫中也查詢不到,那麼就不會將資料放入到快取中,後面如果還有類似源源不斷的請求,最後都會壓到資料庫來處理,從而給資料庫造成巨大的壓力。
二、解決辦法
①、業務層校驗
使用者發過來的請求,根據請求引數進行校驗,對於明顯錯誤的引數,直接攔截返回。
比如,請求引數為主鍵自增id,那麼對於請求小於0的id引數,明顯不符合,可以直接返回錯誤請求。
②、不存在資料設定短過期時間
對於某個查詢為空的資料,可以將這個空結果進行Redis快取,但是設定很短的過期時間,比如30s,可以根據實際業務設定。注意一定不要影響正常業務。
③、布隆過濾器
關於布隆過濾器,後面會詳細介紹。布隆過濾器是一種資料結構,利用極小的記憶體,可以判斷大量的資料“一定不存在或者可能存在”。
對於快取擊穿,我們可以將查詢的資料條件都雜湊到一個足夠大的布隆過濾器中,使用者傳送的請求會先被布隆過濾器攔截,一定不存在的資料就直接攔截返回了,從而避免下一步對資料庫的壓力。
2、快取擊穿
一、概念
快取擊穿:Redis中一個熱點key在失效的同時,大量的請求過來,從而會全部到達資料庫,壓垮資料庫。
這裡要注意的是這是某一個熱點key過期失效,和後面介紹快取雪崩是有區別的。比如淘寶雙十一,對於某個特價熱門的商品資訊,快取在Redis中,剛好0點,這個商品資訊在Redis中過期查不到了,這時候大量的使用者又同時正好訪問這個商品,就會造成大量的請求同時到達資料庫。
二、解決辦法
①、設定熱點資料永不過期
對於某個需要頻繁獲取的資訊,快取在Redis中,並設定其永不過期。當然這種方式比較粗暴,對於某些業務場景是不適合的。
②、定時更新
比如這個熱點資料的過期時間是1h,那麼每到59minutes時,通過定時任務去更新這個熱點key,並重新設定其過期時間。
③、互斥鎖
這是解決快取穿透比較常用的方法。
互斥鎖簡單來說就是在Redis中根據key獲得的value值為空時,先鎖上,然後從資料庫載入,載入完畢,釋放鎖。若其他執行緒也在請求該key時,發現獲取鎖失敗,則睡眠一段時間(比如100ms)後重試。
3、快取雪崩
一、概念
快取雪崩:Redis中快取的資料大面積同時失效,或者Redis當機,從而會導致大量請求直接到資料庫,壓垮資料庫。
對於一個業務系統,如果Redis當機或大面積的key同時過期,會導致大量請求同時打到資料庫,這是災難性的問題。
二、解決辦法
①、設定有效期均勻分佈
避免快取設定相近的有效期,我們可以在設定有效期時增加隨機值;
或者統一規劃有效期,使得過期時間均勻分佈。
②、資料預熱
對於即將來臨的大量請求,我們可以提前走一遍系統,將資料提前快取在Redis中,並設定不同的過期時間。
③、保證Redis服務高可用
前面我們介紹過Redis的哨兵模式和叢集模式,為防止Redis叢集單節點故障,可以通過這兩種模式實現高可用。