面试官问:说一说redis过期删除策略与内存淘汰策略

前言

Redis 的内存淘汰策略和过期删除策略,可能一问都说的都是内存淘汰的策略,忽略了过期删除策略,这两种策略有何不同?虽然这两个机制虽然都是做删除的操作,但是触发的条件和使用的策略都是不同的。

过期删除策略

redis中可以对key设置过期时间,过期时间到了,是不是要清理掉这些key,释放占用的内存。redis内部自动清理这些key的工作机制,就是过期策略。

设置过期时间

  • set ex :设置键值对的时候,同时指定过期时间(精确到秒);
  • set px :设置键值对的时候,同时指定过期时间(精确到毫秒);
  • setex :设置键值对的时候,同时指定过期时间(精确到秒)。

如果你想查看某个 key 剩余的存活时间,可以使用 TTL 命令。

三种策略

定时删除

在设置某个 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毫秒进行一次定期删除操作,清理过期键,并在需要时关闭闲置的客户端连接。

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:

  
CONFIG SET maxmemory-samples 10

总之,通过修改Redis的maxmemory-samples配置项,可以设置一次检查多少个过期键。根据服务器的性能和负载情况,可以适当调整这个值。

手工检查

上面的介绍的三种策略,有利有弊,如果对redis的内存占用率非常在意,可以人工主动检查,利用惰性删除这种策略对过期key进行删除操作

具体操作步骤如下:

  • 使用redis-rdb-tools这个工具对rdb文件分析

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的最大内存

CONFIG SET maxmemory 4gb

我设置了4gb的内存,如果超过4gb,就要进行数据的淘汰。那淘汰哪些数据呢,就要根据淘汰的策略决定

策略

Redis 4.0 版本以后一共提供了 8 种数据淘汰策略,从淘汰数据的候选集范围来看,我们有两种候选范围:一种是所有数据都是候选集,一种是设置了过期时间的数据是候选集。无论是面向哪种候选数据集进行淘汰数据选择,我们都有三种策略,分别是随机选择,根据 LRU 算法选择,以及根据 LFU 算法选择

设置过期时间:

  1. volatile-ttl 在筛选时,会针对设置了过期时间的键值对,根据过期时间的先后进行删除,越早过期的越先被删除。
  2. volatile-random 就像它的名称一样,在设置了过期时间的键值对中,进行随机删除。
  3. volatile-lru 会使用 LRU 算法筛选设置了过期时间的键值对。
  4. volatile-lfu 会使用 LFU 算法选择设置了过期时间的键值对

所有数据进行淘汰:

  1. allkeys-random 策略,从所有键值对中随机选择并删除数据;
  2. allkeys-lru 策略,使用 LRU 算法在所有数据中进行筛选。
  3. allkeys-lfu 策略,使用 LFU 算法在所有数据中进行筛选。

不淘汰数据:

noeviction:不淘汰任何数据,当内存不足时,新增操作会报错,Redis 默认内存淘汰策略;

如何设置策略

查看目前的策略
config get  maxmemory-policy

根据自身的实际情况 选择一种策略进行设置
config set  maxmemory-policy volatile-lfu

算法

LRU 算法:淘汰最近最少使用的数据,它是根据时间维度来选择将要淘汰的元素,即删除掉最长时间没被访问的元素。

LFU 算法:淘汰最不频繁访问的数据,它是根据频率维度来选择将要淘汰的元素,即删除访问频率最低的元素。如果两个元素的访问频率相同,则淘汰最久没被访问的元素。

总结

内存淘汰策略:Redis 的运行内存已经超过 Redis 设置的最大内存之后,则会使用内存淘汰策略删除符合条件的 key,释放出空间,为后续新增的数据使用

过期删除策略:key的过期时间到了,就要删除,释放空间

写作不易,刚好你看到,刚好对你有帮助,动动小手,点点赞,欢迎转发,有疑问的欢迎留言或者私信讨论,有问必回。

你可能感兴趣的:(redis,数据库,缓存)