过期删除和内存淘汰
文章目录
一:过期删除策略
1:设置过期时间
set <key> <value> ex <n>
:设置键值对的时候,同时指定过期时间【精确到秒】set <key> <value> px <n>
:设置键值对的时候,同时指定过期时间(精确到毫秒)setex <key> <n> <value>
:设置键值对的时候,同时指定过期时间(精确到秒)
如果你想查看某个 key 剩余的存活时间,可以使用TTL <key>
命令
2:三种删除策略
2.1:定时删除【内存友好,CPU不好】
在设置某个 key 的过期时间同时,我们创建一个定时器,让定时器在该过期时间到来时,立即执行对其进行删除的操作
- 优点:通过使用定时器,可以保证过期 key 可以被尽快的删除,并且释放过期 key 所占用的内存
- 缺点:对 CPU 是不友好的,当过期键比较多的时候,删除过期 key 会占用相当一部分的 CPU 资源,对服务器的响应时间和吞吐量造成影响
2.2:惰性删除【内存不好,CPU友好】
惰性删除,当一个键值对过期的时候,只有再次用到这个键值对的时候才去检查删除这个键值对,也就是如果用不着,这个键值对就会一直存在
- 优点:对 CPU 是友好的,只有在取出键值对的时候才会进行过期检查,这样就不会把 CPU 资源花费在其他无关紧要的键值对的过期删除上。
- 缺点:如果一些键值对永远不会被再次用到,那么将不会被删除,最终会造成内存泄漏,无用的垃圾数据占用了大量的资源,但是服务器却不能去删除。
2.3:定期删除【二者整合】
每个一段时间就对一些 key 进行采样检查,检查是否过期,如果过期就进行删除:
- 采样一定个数的key,采样的个数可以进行配置,并将其中过期的 key 全部删除
- 如果过期 key 的占比超过可接受的过期 key 的百分比,则重复删除的过程,直到过期key的比例降至可接受的过期 key 的百分比以下。
- 优点:定期删除,通过控制定期删除执行的时长和频率,可以减少删除操作对 CPU 的影响,同时也能较少因过期键带来的内存的浪费
- 缺点:执行的频率不太好控制 频率过快对 CPU 不友好,如果过慢了就会对内存不太友好,过期的键值对不能及时的被删除掉
3:定期删除相关参数设置
3.1:hz:每秒执行定期删除事件
Redis服务器会每隔一段时间(hz确定)主动进行过期键的删除。这种策略通过在后台线程中扫描一定数量的数据库键并删除过期键,以减少对客户端请求的影响。定期删除的执行频率可以通过调整hz配置项来控制
config set hz 200
配置项的默认值是10,即每秒执行10次基于时间的事件。
这意味着Redis服务器会每100毫秒进行一次定期删除操作,清理过期键,并在需要时关闭闲置的客户端连接
3.2: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
4:手工检查 + 惰性策略
上面的介绍的三种策略,有利有弊,如果对redis的内存占用率非常在意,可以人工主动检查
然后利用惰性策略对过期key进行删除操作
使用redis-rdb-tools【https://github.com/sripathikrishnan/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 高效的运行
1:设置redis的最大内存
config set maxmemory 4gb
这里设置了4gb的内存,如果超过4gb,就要进行数据的淘汰。那淘汰哪些数据呢,就要根据淘汰的策略决定
2:淘汰策略
Redis 4.0 版本以后一共提供了 8 种数据淘汰策略。从淘汰数据的候选集范围来看,我们有两种候选范围:
- 一种是所有数据都是候选集
- 一种是设置了过期时间的数据是候选集。
无论是面向哪种候选数据集进行淘汰数据选择。我们都有三种策略:随机选择 & LRU 算法 & LFU 算法选择
- LRU:淘汰最近最少使用的数据,它是根据时间维度来选择将要淘汰的元素,即删除掉最长时间没被访问的元素
- LFU:淘汰最不频繁访问的数据,它是根据频率维度来选择将要淘汰的元素,即删除访问频率最低的元素。如果两个元素的访问频率相同,则淘汰最久没被访问的元素
2.1:设置过期时间:
volatile-ttl
会针对设置了过期时间的键值对,根据过期时间的先后进行删除volatile-random
在设置了过期时间的键值对中,进行随机删除。volatile-lru
会使用 LRU 算法筛选设置了过期时间的键值对。volatile-lfu
会使用 LFU 算法选择设置了过期时间的键值对
2.2:所有数据进行淘汰:
allkeys-random
策略,从所有键值对中随机选择并删除数据;allkeys-lru
策略,使用 LRU 算法在所有数据中进行筛选。allkeys-lfu
策略,使用 LFU 算法在所有数据中进行筛选。
2.3:不淘汰数据:
noeviction
不淘汰任何数据,当内存不足时,新增操作会报错,Redis 默认内存淘汰策略;
3:策略的设置
# 查看目前的策略
config get maxmemory-policy
# 根据自身的实际情况 选择一种策略进行设置
config set maxmemory-policy volatile-lfu