前言
Redis 的内存淘汰策略和过期删除策略,可能一问都说的都是内存淘汰的策略,忽略了过期删除策略,这两种策略有何不同?虽然这两个机制虽然都是做删除的操作,但是触发的条件和使用的策略都是不同的。
过期删除策略
redis中可以对key设置过期时间,过期时间到了,是不是要清理掉这些key,释放占用的内存。redis内部自动清理这些key的工作机制,就是过期策略。
设置过期时间
set <key> <value> ex <n>
:设置键值对的时候,同时指定过期时间(精确到秒);set <key> <value> px <n>
:设置键值对的时候,同时指定过期时间(精确到毫秒);setex <key> <n> <valule>
:设置键值对的时候,同时指定过期时间(精确到秒)。
如果你想查看某个 key 剩余的存活时间,可以使用 TTL <key>
命令。
三种策略
定时删除
在设置某个 key 的过期时间同时,我们创建一个定时器,让定时器在该过期时间到来时,立即执行对其进行删除的操作。
优点:
通过使用定时器,可以保证过期 key 可以被尽快的删除,并且释放过期 key 所占用的内存
缺点:
对 CPU 是不友好的,当过期键比较多的时候,删除过期 key 会占用相当一部分的 CPU 资源,对服务器的响应时间和吞吐量造成影响。
惰性删除
惰性删除,当一个键值对过期的时候,只有再次用到这个键值对的时候才去检查删除这个键值对,也就是如果用不着,这个键值对就会一直存在。
优点:
对 CPU 是友好的,只有在取出键值对的时候才会进行过期检查,这样就不会把 CPU 资源花费在其他无关紧要的键值对的过期删除上。
缺点:
如果一些键值对永远不会被再次用到,那么将不会被删除,最终会造成内存泄漏,无用的垃圾数据占用了大量的资源,但是服务器却不能去删除。
定期删除
定期删除是对上面两种删除策略的一种整合和折中
每个一段时间就对一些 key 进行采样检查,检查是否过期,如果过期就进行删除
1、采样一定个数的key,采样的个数可以进行配置,并将其中过期的 key 全部删除;
2、如果过期 key 的占比超过可接受的过期 key 的百分比
,则重复删除的过程,直到过期key的比例降至可接受的过期 key 的百分比
以下。
优点:
定期删除,通过控制定期删除执行的时长和频率,可以减少删除操作对 CPU 的影响,同时也能较少因过期键带来的内存的浪费。
缺点:
执行的频率不太好控制 频率过快对 CPU 不友好,如果过慢了就会对内存不太友好,过期的键值对不能及时的被删除掉
参数设置
hz
Redis服务器会每隔一段时间(由hz
配置项决定)主动进行过期键的删除。这种策略通过在后台线程中扫描一定数量的数据库键并删除过期键,以减少对客户端请求的影响。定期删除的执行频率可以通过调整hz
配置项来控制
hz
配置项的默认值是10,即每秒执行10次基于时间的事件。这意味着Redis服务器会每100毫秒进行一次定期删除操作,清理过期键,并在需要时关闭闲置的客户端连接。
js
config set hz 200
maxmemory-samples
在Redis中,可以使用maxmemory-samples
配置项来设置每次清理过期键时要检查的最大键数。这个配置项决定了Redis在执行清理过期键任务时一次检查多少个键。
默认情况下,maxmemory-samples
的值是5,表示Redis每次清理过期键时会检查5个键。这个值可以根据实际需求进行调整。
要修改maxmemory-samples
的值,可以在redis.conf文件中找到相应的配置项,并将其设置为所需的值。然后,重新启动Redis服务器使配置生效。
需要注意的是,增加maxmemory-samples
的值可能会增加Redis服务器的处理开销,因为每次清理过期键任务都需要检查更多的键。因此,应根据服务器的性能和负载情况来适当调整maxmemory-samples
的值。
另外,还可以通过调用CONFIG SET
命令动态地修改maxmemory-samples
的值,而不需要重启Redis服务器。例如,可以使用以下命令将maxmemory-samples
的值设置为10:
sql
CONFIG SET maxmemory-samples 10
总之,通过修改Redis的maxmemory-samples
配置项,可以设置一次检查多少个过期键。根据服务器的性能和负载情况,可以适当调整这个值。
手工检查
上面的介绍的三种策略,有利有弊,如果对redis的内存占用率非常在意,可以人工主动检查,利用惰性删除
这种策略对过期key进行删除操作
具体操作步骤如下:
- 使用redis-rdb-tools这个工具对rdb文件分析
js
rdb -c memory /var/redis/6379/dump.rdb --bytes 128 -f memory.csv
database,type,key,size_in_bytes,encoding,num_elements,len_largest_element,expiry
0,string,urn:userbrowselprecordmodel:9365489,272,string,169,169,
0,string,urn:weixinuserinfomodel:oIUvls3Wcaf7dU9IBuwU6cwZVh58,288,string,182,182,
0,string,urn:tokeninfo:1e0b01e7f2bdf8a0244783cde2275e18,288,string,169,169,
0,string,yd_7986ACF279F2C7745586BADA1594459D,136,string,16,16,2025-01-23T17:15:47.316000
0,string,urn:userbrowselprecordmodel:38074301,272,string,169,169,
0,string,B7E1D813E574957CF956841E69711B42,136,string,16,16,2025-10-20T09:34:34.680000
0,string,urn:wxnotify:87b0dae4-8675-40f1-b3d3-5d26056bbe3b,416,string,304,304,
0,string,urn:userbrowselprecordmodel:28873589,272,string,169,169,
0,string,70A3040FBB6420AA0B90089ED7212770,136,string,16,16,2025-01-22T12:56:03.823000
输出是csv报告文件,expiry
就是过期时间,读取csv文件,遍历数据,对存在过期时间的,跟当前时间判断,如果小于当前时间,说明已经过期了,那我们就主动访问下,不是去get
,利用EXISTS key
命令触发,reids检查这个key是否要删除。
内存淘汰策略
Redis 的运行内存已经超过 Redis 设置的最大内存之后,则会使用内存淘汰策略删除符合条件的 key,以此来保障 Redis 高效的运行
设置redis的最大内存
js
CONFIG SET maxmemory 4gb
我设置了4gb的内存,如果超过4gb,就要进行数据的淘汰。那淘汰哪些数据呢,就要根据淘汰的策略决定
策略
Redis 4.0 版本以后一共提供了 8 种数据淘汰策略,从淘汰数据的候选集范围来看,我们有两种候选范围:一种是所有数据都是候选集,一种是设置了过期时间的数据是候选集。无论是面向哪种候选数据集进行淘汰数据选择,我们都有三种策略,分别是随机选择,根据 LRU 算法选择,以及根据 LFU 算法选择
设置过期时间:
- volatile-ttl 在筛选时,会针对设置了过期时间的键值对,根据过期时间的先后进行删除,越早过期的越先被删除。
- volatile-random 就像它的名称一样,在设置了过期时间的键值对中,进行随机删除。
- volatile-lru 会使用 LRU 算法筛选设置了过期时间的键值对。
- volatile-lfu 会使用 LFU 算法选择设置了过期时间的键值对
所有数据进行淘汰:
- allkeys-random 策略,从所有键值对中随机选择并删除数据;
- allkeys-lru 策略,使用 LRU 算法在所有数据中进行筛选。
- allkeys-lfu 策略,使用 LFU 算法在所有数据中进行筛选。
不淘汰数据:
noeviction:不淘汰任何数据,当内存不足时,新增操作会报错,Redis 默认内存淘汰策略;
如何设置策略
js
查看目前的策略
config get maxmemory-policy
根据自身的实际情况 选择一种策略进行设置
config set maxmemory-policy volatile-lfu
算法
LRU
算法:淘汰最近最少使用的数据,它是根据时间维度来选择将要淘汰的元素,即删除掉最长时间没被访问的元素。
LFU
算法:淘汰最不频繁访问的数据,它是根据频率维度来选择将要淘汰的元素,即删除访问频率最低的元素。如果两个元素的访问频率相同,则淘汰最久没被访问的元素。
总结
内存淘汰策略
:Redis 的运行内存已经超过 Redis 设置的最大内存之后,则会使用内存淘汰策略删除符合条件的 key,释放出空间,为后续新增的数据使用
过期删除策略
:key的过期时间到了,就要删除,释放空间
写作不易,刚好你看到,刚好对你有帮助,动动小手,点点赞,欢迎转发,有疑问的欢迎留言或者私信讨论,有问必回。