Redis 緩存過期刪除/淘汰策略分析


Redis 緩存過期刪除/淘汰策略分析

Redis 緩存刪除

  1. Redis 鍵過期刪除,定期刪除(主動)和惰性刪除(被動)
  2. Redis 內存不足時,緩存淘汰策略

key 鍵過期刪除

我們用 redis 作為緩存數據庫,設置 k-v 數據的時候,可以給這條數據設置一個過期時間。比如,set 命令設置過期時間:

set testkey redisvalue EX 60

EX: 表示秒, EX 60 表示這個鍵值60秒后過期。

那好,現在就有一個問題了,redis 怎么檢查數據緩存時間到期了?然后刪除它。

想一想,檢測到期數據一般有兩種方法,

第一:主動檢測

第二:被動檢測

什么是主動?

第一種,就是每設置一個 kv 值時,給這個 kv 值設置一個定時器,給它計時,到期就刪除。但是這樣會給 cpu 造成很多壓力。

另外一種,定期掃描 kv 值,檢查到期值在刪除。

什么是被動?

被動就是對這個數據有操作時候才檢查它緩存時間是否到期,如果有到期,就刪除。

刪除步驟:

redis 會將每個設置了過期時間的 key 放到一個獨立的字典集合中,以后會定時遍歷這個字典來刪除到期的 key。

定時遍歷刪除,默認情況每秒檢查 10 次鍵的字典集合,每次從這個集合中隨機檢查 20 個鍵查看是否過期,過期就直接刪除。刪除后還有超過 25% 的集合中鍵過期,繼續隨機抽取 20 個鍵檢測刪除。

還有惰性刪除,就是在客戶端訪問這個 key 時,redis 會對 key 的過期時間進行檢查,過期了就刪除。

Redis 內存不足時緩存淘汰策略

redis 的 8 種緩存淘汰策略

redis.conf 配置文件中,就可以看到 redis 緩存過期淘汰的設置項。

當 Redis 內存快要滿的時候,redis 會執行緩存淘汰策略。

https://github.com/redis/redis/blob/6.2/redis.conf#L994

# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select one from the following behaviors:
#
# volatile-lru -> Evict using approximated LRU, only keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU, only keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key having an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.
#
#
# The default is:
#
# maxmemory-policy noeviction

redis v6.2 版本配置。

maxmemory , redis 提供了一個配置參數來設置 maxmemory(redis 最大可使用內存),這個參數來限制最大內存使用,實際內存超出了這個參數設置時,redis 就根據 maxmemory-policy 的設置策略刪除鍵值,釋放內存空間。

maxmemory-policy 設置,也就是內存淘汰策略,從 redis4.0 開始有8種緩存淘汰策略:

noeviction:默認設置。如果設置的空間滿了,不會刪除任何值,寫操作請求時服務器直接返回錯誤。讀、刪除請求可以繼續服務。

volatile-lru:淘汰設置了過期時間的 key,使用 lru 算法,最近最少使用的 key 先淘汰。注意,沒有設置過期時間的 key 就不淘汰。why?我們是不是還有一些持久化 key 的需求。

allkeys-lru:上面 volatile-lru 是部分淘汰 key(設置了過期時間的 key)。而這個是淘汰所有的 key,不管有沒有設置過期時間,都會淘汰。也是使用 lru 最近最少使用算法。

volatile-lfu:淘汰設置了過期時間的 key,使用 lfu 算法,使用頻率最少的 key 先淘汰。

allkeys-lfu:淘汰所有的 key,根據 lfu 算法。

volatile-random:淘汰設置了過期時間的 key,隨機算法。

allkeys-random:淘汰所有的 key,不管是否設置過期時間,隨機算法。

volatile-ttl:淘汰設置了過期時間的 key,根據 key 的 ttl 剩余時間,也就是說 ttl 越小越先被淘汰。

說明:使用 lfu 淘汰算法的都是 redis4.0 以上版本。

緩存淘汰算法

  • lru:Least Recently Used,最近最少使用。
  • lfu:Least Frequently Used,使用頻率最少的,最不經常使用。
  • random:隨機算法。
  • ttl:根據 key 設置的 ttl 剩余時間。

random 和 ttl 這 2 種緩存淘汰算法容易理解。

但是 lru 和 lfu 不容易理解,他們的區別是什么呢?

LRU :

Least Recently Used,最近最少使用,與使用的最后一次時間有關,淘汰最近使用、時間離現在最久的。

算法思想:

如果一個數據最近一段時間沒有被訪問到,那么以后它被訪問到的可能性也比較小。

LFU :

Least Frequently Used,最近一段時間使用頻率最少,與使用的次數有關,淘汰使用次數最少的。

LFU 是 redis4.0 以后才出現的,4.0 以前都是 LRU。那 LFU 解決的是什么問題呢?

看下面的圖,來自 antirez 博客文章 Random notes on improving the Redis LRU algorithm:

~~~~~A~~~~~A~~~~~A~~~~A~~~~~A~~~~~A~~|
~~B~~B~~B~~B~~B~~B~~B~~B~~B~~B~~B~~B~|
~~~~~~~~~~C~~~~~~~~~C~~~~~~~~~C~~~~~~|
~~~~~D~~~~~~~~~~D~~~~~~~~~D~~~~~~~~~D|

每個波浪代表 1 秒,key A 每 5 秒訪問一次,key B 每 2 秒訪問一次,key C 和 key D 每 10 秒訪問一次。"|" 表示訪問結束。

看圖,從結束 "|" 位置看(實際是以時間為標准看),D 是最近一次訪問。但是,從上圖整體來看, B 是使用次數最多,也就是訪問頻率最多。如果需要淘汰的話,應該淘汰 D 才合理,LFU 才是比較合理的策略。

如果是在一段時間內,數據使用頻率更高的場景中,那么 LFU 算法比 LRU 算法命中率更高。

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM