這是決定在使用快取時就該考慮的問題。
快取的資料在資料來源發生變更時需要對快取進行更新,資料來源可能是 db,也可能是遠端服務。更新的方式可以是主動更新。資料來源是 db 時,可以在更新完 db 後就直接更新快取。
當資料來源不是 db 而是其他遠端服務,可能無法及時主動感知資料變更,這種情況下一般會選擇對快取資料設定失效期,也就是資料不一致的最大容忍時間。
這種場景下,可以選擇失效更新,key 不存在或失效時先請求資料來源獲取最新資料,然後再次快取,並更新失效期。
但這樣做有個問題,如果依賴的遠端服務在更新時出現異常,則會導致資料不可用。改進的辦法是非同步更新,就是當失效時先不清除資料,繼續使用舊的資料,然後由非同步執行緒去執行更新任務。這樣就避免了失效瞬間的空窗期。另外還有一種純非同步更新方式,定時對資料進行分批更新。實際使用時可以根據業務場景選擇更新方式。
第二個問題是資料不一致的問題,可以說只要使用快取,就要考慮如何面對這個問題。快取不一致產生的原因一般是主動更新失敗,例如更新 db 後,更新 redis 因為網路原因請求超時;或者是非同步更新失敗導致。
解決的辦法是,如果服務對耗時不是特別敏感可以增加重試;如果服務對耗時敏感可以通過非同步補償任務來處理失敗的更新,或者短期的資料不一致不會影響業務,那麼只要下次更新時可以成功,能保證最終一致性就可以。
快取穿透。產生這個問題的原因可能是外部的惡意攻擊,例如,對使用者資訊進行了快取,但惡意攻擊者使用不存在的使用者id頻繁請求介面,導致查詢快取不命中,然後穿透 db 查詢依然不命中。這時會有大量請求穿透快取訪問到 db。
解決的辦法如下。
對不存在的使用者,在快取中儲存乙個空物件進行標記,防止相同 id 再次訪問 db。不過有時這個方法並不能很好解決問題,可能導致快取中儲存大量無用資料。
使用 bloomfilter 過濾器,bloomfilter 的特點是存在性檢測,如果 bloomfilter 中不存在,那麼資料一定不存在;如果 bloomfilter 中存在,實際資料也有可能會不存在。非常適合解決這類的問題。
快取擊穿,就是某個熱點資料失效時,大量針對這個資料的請求會穿透到資料來源。
解決這個問題有如下辦法。
可以使用互斥鎖更新,保證同乙個程序中針對同乙個資料不會併發請求到 db,減小 db 壓力。
使用隨機退避方式,失效時隨機 sleep 乙個很短的時間,再次查詢,如果失敗再執行更新。
針對多個熱點 key 同時失效的問題,可以在快取時使用固定時間加上乙個小的隨機數,避免大量熱點 key 同一時刻失效。
快取雪崩,產生的原因是快取掛掉,這時所有的請求都會穿透到 db。
解決方法:
使用快速失敗的熔斷策略,減少 db 瞬間壓力;
使用主從模式和集群模式來盡量保證快取服務的高可用。
Redis 之 快取常見問題
使用者查詢乙個資料,快取中沒有,資料庫中也沒有。這樣頻繁的訪問資料庫導致資料庫宕機。解決方法 1.請求加乙個過濾器 布隆過濾器 對所有可能的查詢的引數以hash形式儲存,在控制層先進行校驗,不符合則丟棄。這樣避免資料庫壓力。布隆過濾器 2.快取空物件 查詢為空則在快取中儲存乙個空物件。乙個key訪問...
Redis 常見問題 快取穿透
問題描述 針對 db 中不存在的資料來源,每次請求快取和資料庫都不存在 造成後果 應用伺服器壓力變大 redis 命中率大幅度降低 資料庫壓力鉅增甚至 down 掉 該現象對於 redis 無影響,奔潰的是資料庫 造成原因 頻繁訪問不存在資料 解決方案 1.空值快取 查詢資料庫返回為 null 時也...
快取常見問題
情況 在流量大時,如果有人利用不存在的key頻繁去訪問我們的應用,可能會導致資料庫掛掉。原因 查詢乙個不存在的資料,由於快取是不命中時被動寫入,並且出於容錯考慮,如果從儲存層查不到資料則不寫入快取,這導致這個不存在的資料每次請求都要到儲存層去查詢,失去了快取的意義。解決方案 1 布隆過濾器 將所有可...