Redis是一個完全開源免費的高性能非關系型(NOSQL)的key-value數據庫。 Redis不可能把所有的數據都緩存起來(內存昂貴且有限),所以Redis需要對數據 設置過期時間,并采用的是惰性刪除+定期刪除兩種策略對過期鍵刪除。Redis對過期鍵的策略+持久化 如果緩存數據設置的過期時間是相同的,并且Redis恰好將這部分數據全部刪光了。這就會導致在這段時 間內,這些緩存同時失效,全部請求到數據庫中。
Redis中緩存的數據大面積同時失效,或者Redis宕機,從而會導致大量請求直接到數據庫,壓垮數據庫 緩存雪崩如果發生了,很可能就把我們的數據庫搞垮,導致整個服務癱瘓!
解決方法: 在緩存的時候給過期時間加上一個隨機值,這樣就會大幅度的減少緩存在同一時間過期。 對于“Redis掛掉了,請求全部走數據庫”這種情況,我們可以有以下的思路: 事發前:實現Redis的高可用(主從架構+Sentinel 或者Redis Cluster),盡量避免Redis掛掉這種情況發生。
事發中:萬一Redis真的掛了,我們可以設置本地緩存+限流,盡量避免我們的 數據庫被干掉(起碼能保證我們的服務還是能正常工作的)
事發后:redis持久化,重啟后自動從磁盤上加載數據,快速恢復緩存數據。
緩存穿透? 緩存穿透是指查詢一個一定不存在的數據。由于緩存不命中,并且出于容錯考慮,如果從數據庫查不到 數據則不寫入緩存,這將導致這個不存在的數據每次請求都要到數據庫去查詢,失去了緩存的意義 請求的數據在緩存大量不命中,導致請求走數據,也可能壓垮數據庫,導致整個服務癱瘓!
如何解決緩存穿透 由于請求的參數是不合法的(每次都請求不存在的參數),于是我們可以使用布隆過濾器(BloomFilter)提前攔截,不合法就不讓這個請求到數據庫層! 當我們從數據庫找不到的時候,我們也將這個空對象設置到緩存里邊去。下次再請求的時候,就可以從 緩存里邊獲取了。 這種情況我們一般會將空對象設置一個較短的過期時間。
緩存擊穿 Redis中一個熱點key在失效的同時,大量的請求過來,從而會全部到達數據庫,壓垮數據庫。 這里要注意的是這是某一個熱點key過期失效,和緩存雪崩是有區別的。比如淘寶雙十一,對于某個特價熱門的商品信息,緩存在Redis中,剛好0點,這個商品信息在Redis中過期查不到了,這時候大量的用戶又同時正好訪問這個商品,就會造成大量的請求同時到達數據庫。
解決辦法 設置熱點數據"永不過期" 或者定時更新,加上互斥鎖:上面的現象是多個線程同時去查詢數據庫的這條數據,我們 可以在第一個查詢數據的請求上使用一個互斥鎖來鎖住它 其他的線程走到這一步拿不到鎖就等著,等 一個線程查詢到了數據,然后將數據放到redis緩存起來。 后面的線程進來發現已經有緩存了,就直接走緩存。