緩存雪崩#
緩存雪崩:當大量緩存數據在同一時間過期(失效)或者 Redis 故障宕機時,如果此時有大量的用戶請求,無法在 Redis 中處理,那麼這些請求將會直接訪問數據庫,從而導致數據庫壓力驟增,嚴重的話會導致數據庫崩潰宕機,進而導致整個系統崩潰。
解決方案:
- 避免為大量的數據設置成同一過期時間,我們可以在設置過期時間時添加一個隨機數,這樣就可以保證數據不會在同一時間過期了。
- 互斥鎖,如果發現訪問的數據不在 Redis 裡,就加個互斥鎖,保證同一時間內只有一個請求來構建緩存(從數據庫讀取數據,再將數據更新到 Redis),當緩存構建完成後,再釋放鎖。未能獲取到互斥鎖的請求,要麼等待鎖釋放後,重新讀取緩存,要麼直接返回空值或者默認值。實現互斥鎖時,要設置超時時間,不然某個請求拿到鎖後,如果請求發生意外情況而一直阻塞,一直不釋放鎖,這時其他請求不能拿到鎖,整個系統就會出現無響應的現象。
- 後台更新緩存,業務線程不再負責更新緩存,緩存不必設置有效期,讓緩存 “永久有效”,並將更新緩存的工作交由後台線程定時更新。
緩存擊穿#
緩存擊穿:如果緩存中的某些熱點數據過期了,此時大量的請求訪問這些熱點數據,就無法從緩存中讀取,進而直接訪問數據庫,導致數據庫被高並發請求沖垮。
解決方案:
- 互斥鎖,保證同一時間內只有一個線程更新緩存,未能獲取到互斥鎖的請求,要麼等待鎖釋放,要麼直接返回空值或默認值。
- 不給熱點數據設置過期時間,由後台異步更新緩存,或者在熱點數據要過期前,提前通知後台線程更新緩存並重新設置過期時間。
緩存穿透#
緩存穿透:當用戶訪問的數據,既不在緩存中,也不在數據庫中,導致請求在訪問緩存時失效,再去訪問數據庫,發現數據庫中也沒有這些數據,沒辦法構建緩存為後續的請求服務。當有大量這樣的請求時,數據庫的壓力會驟增,進而導致數據庫崩潰。
解決方案:
- 非法請求判斷:在請求入口處加入請求參數校驗,檢查參數是否合理有效,如果是非法參數,直接返回錯誤,避免進一步訪問緩存和數據庫。
- 緩存空值或默認值,針對某些要查詢的數據,在緩存中設置一個空值或默認值,這樣後續的請求可以直接從緩存中讀取到空值或者默認值,返回給應用程序,而不會進一步查詢數據庫。
- 布隆過濾器:當用戶請求到來時,可以通過查詢布隆過濾器來快速判斷數據是否存在,如果不存在,就不用再查詢數據庫了,這樣就能保證數據庫正常運行。