Redis-缓存淘汰与过期删除
Redis-缓存淘汰与过期删除
xiaoyan过期删除策略和内存淘汰策略有什么区别?
- 过期删除策略是将已过期的键值进行删除,Redis采用的删除策略是惰性删除和定时删除。
- 内存淘汰策略是在内存满了的时候,redis触发内存淘汰策略,来淘汰一些不必要的内存资源,以腾出空间来保存新的内容。
Redis内存淘汰策略
在32位系统中,Redis的maxmemory
默认值为3GB,这是因为32位系统最高支持4GB内存,而系统本身需要一定的内存资源来运行。为了避免因内存不足而导致Redis崩溃,设置maxmemory
为3GB是一个合理的默认值。
Redis提供了8种内存淘汰策略,这些策略可以根据是否进行数据淘汰分为两类:
1. 不进行数据淘汰
- noeviction(Redis 3.0之后默认使用的策略):当运行内存达到最大内存时,不会淘汰任何数据。如果有新的数据插入,Redis会返回错误。但对于普通的查询或删除操作,Redis可以正常运行。
2. 进行数据淘汰
针对“进行数据淘汰”这一类策略,又可以继续分为“在设置了过期时间的数据中淘汰”和“在所有数据范围内淘汰”两类。
“在设置了过期时间的数据中淘汰”:
- volatile-random:随机淘汰设置了过期时间的数据。
- volatile-ttl:优先淘汰过期时间最早的数据。
- volatile-lru(Redis 3.0之前默认使用策略):淘汰所有设置了过期时间的数据中,最久未使用的键值。
- volatile-lfu:淘汰所有设置了过期时间的数据中,最少使用的数据。
“在所有数据范围中进行淘汰”:
- allkeys-random:随机淘汰任意键值
- allkey-lru:淘汰整个键值中最久未使用的键值
- allkeys-lfu:淘汰整个键值中最少使用的键值
Redis过期删除策略
Redis使用惰性删除
和定期删除
相结合的过期删除策略,以在CPU使用时间和避免内存空间浪费之间取得平衡。
惰性删除
Redis的惰性删除策略由db.c
文件中的expireIfNeeded
函数实现。惰性删除的核心思想是:在访问或修改key之前,先检查key是否过期,如果过期则删除该key。
以下是expireIfNeeded函数源码:
1 | int expireIfNeeded(redisDb *db, robj *key) { |
- 检查key是否过期:在访问或修改key之前,调用
expireIfNeeded
函数检查key是否过期。 - 删除过期key:如果key过期,则根据
lazyfree_lazy_expire
参数配置,选择异步删除(dbAsyncDelete
)或同步删除(dbSyncDelete
)。 - 返回结果:如果key过期并被删除,返回
null
给客户端;如果key未过期,则正常返回键值对给客户端。
定期删除
Redis的定期删除策略是每隔一段时间从内存中随机抽取一定数量的key进行检查,并删除其中过期的key。定期删除的目的是避免内存中积累过多的过期key,从而浪费内存空间。
定期删除的配置
- 间隔检查时间:默认是1秒检查10次,可以通过
redis.conf
文件进行配置。 - 随机抽查数量:在源码中,定期删除的实现在
expire.c
文件下的activeExpireCycle
函数中,其中随机抽查的数量由ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP
定义,数值是20。
定期删除的流程
- 随机抽取key:从过期字典中随机抽取20个key。
- 检查并删除过期key:检查这些key是否已过期,并删除已过期的key。
- 循环检查:如果本轮已过期的key超过5个,则继续抽取20个key再次进行检查删除,直到不满足该条件,退出。
Redis缓存为什么不过期直接删
在Redis中,过期key的删除策略是惰性删除和定期删除相结合的方式。然而,在内存不紧张但CPU紧张的情况下,Redis并不会立即删除过期的key,而是选择延迟删除。这种设计主要是为了在CPU资源紧张的情况下,优先保证业务性能,避免因频繁删除过期key而占用过多的CPU时间。