redis的过期策略
Redis 所有的數據結構都可以設置過期時間,時間一到,就會自動刪除。你可以想象 Redis 內部有一個死神,時刻盯著所有設置了過期時間的 key,壽命一到就會立即收割。
你還可以進一步站在死神的角度思考,會不會因為同一時間太多的 key 過期,以至于忙不過來。同時因為 Redis 是單線程的,收割的時間也會占用線程的處理時間,如果收割的太過于繁忙,會不會導致線上讀寫指令出現卡頓。
過期的 key 集合
redis 會將每個設置了過期時間的 key 放入到一個獨立的字典中,以后會定時遍歷這個字典來刪除到期的 key。除了定時遍歷之外,它還會使用惰性策略來刪除過期的 key,所謂惰性策略就是在客戶端訪問這個 key 的時候,redis 對 key 的過期時間進行檢查,如果過期了就立即刪除。定時刪除是集中處理,惰性刪除是零散處理。
定時掃描策略
Redis 默認會每秒進行十次過期掃描,過期掃描不會遍歷過期字典中所有的 key,而是 采用了一種簡單的貪心策略。
1、從過期字典中隨機 20 個 key;
2、刪除這 20 個 key 中已經過期的 key;
3、如果過期的 key 比率超過 1/4,那就重復步驟 1;
同時,為了保證過期掃描不會出現循環過度,導致線程卡死現象,算法還增加了掃描時間的上限,默認不會超過 25ms。
設想一個大型的 Redis 實例中所有的 key 在同一時間過期了,會出現怎樣的結果?
毫無疑問,Redis 會持續掃描過期字典 (循環多次),直到過期字典中過期的 key 變得稀疏,才會停止 (循環次數明顯下降)。這就會導致線上讀寫請求出現明顯的卡頓現象。導致這 種卡頓的另外一種原因是內存管理器需要頻繁回收內存頁,這也會產生一定的 CPU 消耗。
也許你會爭辯說“掃描不是有 25ms 的時間上限了么,怎么會導致卡頓呢”?這里打個 比方,假如有 101 個客戶端同時將請求發過來了,然后前 100 個請求的執行時間都是 25ms,那么第 101 個指令需要等待多久才能執行?2500ms,這個就是客戶端的卡頓時間, 是由服務器不間斷的小卡頓積少成多導致的。
所以業務開發人員一定要注意過期時間,如果有大批量的 key 過期,要給過期時間設置 一個隨機范圍,而不能全部在同一時間過期。
# 在目標過期時間上增加一天的隨機時間 redis.expire_at(key, random.randint(86400) + expire_ts)在一些活動系統中,因為活動是一期一會,下一期活動舉辦時,前面幾期的很多數據都可以丟棄了,所以需要給相關的活動數據設置一個過期時間,以減少不必要的 Redis 內存占用。如果不加注意,你可能會將過期時間設置為活動結束時間再增加一個常量的冗余時間, 如果參與活動的人數太多,就會導致大量的 key 同時過期。
從庫的過期策略
從庫不會進行過期掃描,從庫對過期的處理是被動的。主庫在 key 到期時,會在 AOF 文件里增加一條 del 指令,同步到所有的從庫,從庫通過執行這條 del 指令來刪除過期的 key。
因為指令同步是異步進行的,所以主庫過期的 key 的 del 指令沒有及時同步到從庫的話,會出現主從數據的不一致,主庫沒有的數據在從庫里還存在。
總結
以上是生活随笔為你收集整理的redis的过期策略的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java Optional 的 orEl
- 下一篇: redis的info指令详解