參考鏈接:
產生原因:
redis的從庫是無法主動的刪除已經過期的key的,所以如果做了讀寫分離,就很有可能在從庫讀到臟數據
解決方法:
通過一個程序循環便利所有的key,例如scan
升級到reidis3.2
詳細分析:
我們首先來了解一下redis的三種過期策略:
1 惰性刪除:當讀寫一個已經過期的key時,會觸發惰性刪除策略,直接刪除掉這個過期key,但是,顯然,這個是被動的
2 定期刪除:由於惰性刪除策略無法保證冷數據(偶爾會被查詢或調用的數據)被及時刪掉,所以redis會定期主動淘汰一批已經過期的key
3 主動刪除:當前內存超過maxmemory限定時,觸發主動清理策略,該策略由2啟動參數的配置決定,可配置參數及說明:
volatile-lru:從已設置過期時間的數據集中根據LRU算法刪除數據(redis3.0之前的默認策略)
volatile-ttl:從已設置過期時間的數據集中挑選過期時間最小的數據刪除
volatile-random:從已設置過期時間的數據集中隨機選擇數據刪除
allkeys-lru:從所有數據集中根據LRU算法刪除數據
allkeys-random:從所有數據集中任意選擇刪除數據
noenviction:禁止從內存中刪除數據(從redis3.0開始的默認策略)
maxmemory-samples:刪除數據的抽樣樣本數,redis3.0之前默認樣本數為3,redis3.0之后默認樣本數為5,該參數過小會導致主動刪除策略不准確,過大會消耗多余的cpu
定期刪除:
redis定位為輕量、快速的內存數據庫,所以如果為所有key都加上定時器,過期即刪除的定時策略顯然后消耗大量的性能,這與redis的價值觀不符;而且過期即刪的定時策略只會在主庫上進行,對於目前redis使用的組合策略來說,單位時間過期的數據量越多,越可能會帶來key的過期延遲,對於做了讀寫分離的業務,很容易導致從庫讀取到過期的臟數據
如何避免從庫讀取到臟數據:
1 通過scan命令掃庫:
當redis中的key被scan的時候,相當於訪問了該key,同樣也會做過期檢測,充分發揮redis惰性刪除的策略,這個方法能大大降低了臟數據讀取的概率,答案缺點也比較明顯,會造成一定的數據庫壓力,謹慎合理是喲個,夠則有可能影響線上業務的效率
2 升級redis到新的版本:
在redis3.2中,redis加入了一個新特性來解決主從不一致導致讀取到過期數據問題,在db.c文件中,作者對lookupKeyRead做了相應的修改,增加了key是否過期以及對主從庫的判斷,如果key已過期,當前訪問的master則返回null;當前訪問的是從庫,且執行的是只讀命令也返回null(老版本從庫真實的返回該操作的結果,如果該key過期后主庫沒有刪除,就返回為null)
