Redis内存回收用法及说明

 更新时间:2025年12月24日 09:16:35   作者:姓蔡小朋友  
Redis通过配置文件设置最大内存空间,当达到上限时,会使用过期策略和淘汰策略来管理内存,过期策略包括惰性删除和周期删除,而淘汰策略则根据内存使用情况主动删除部分key以释放空间

Redis可以通过修改配置文件maxmemory为Redis设置最大内存空间占用,当内存存储达到上限时,就无法存储更多数据了。

Redis提供了过期策略和淘汰策略来避免内存存储达到上限

一、过期策略

过期策略就是通过expire命令给key设置TTL,key过期时,key对应的内存会被释放。

redisDB维护两个Dict:dict、expires,dict记录所有redisObject-内存首址键值对、expires记录设置了过期时间的redisObject-过期时间键值对。

1.惰性删除

惰性删除在访问(CRUD)key时执行:首先根据key从dict中找到对应的redisObject,然后检查key记录在expires中的TTL,如果过期那么释放key的内存空间。

存在的问题:如果key过期了但是永远不会被访问,那么惰性删除策略下该key的内存空间永远不会被释放。

2.周期删除

为所有key设置同一个定时任务,周期性的抽样部分key,检查是否过期,如果过期执行删除操作:

SLOW模式:redis单线程初始化时(初始化epoll阶段)设置server.hz频率(默认100ms)定期检查并清理过期key,不在主线程main函数中

  • 执行周期为100ms,执行清理耗时不能超过25%即25ms
  • 首先逐个遍历db,每次取20个key检查并清理过期key
  • 如果时间未达到25ms且刚才检查的过期key比例超过10%,再取20个key检查并清理。
  • (感觉这个任务每100ms执行一次的话,如果不是异步的,应该要抢占主单线程的CPU

FAST模式:每次redis单线程调用epoll_wait阻塞前都会先检查并清理部分过期key(2ms左右)

  • 因为位于主线程的main代码中,所以执行周期为两次调用epoll_wait的间隔,但如果间隔低于2ms那么不会执行FAST清理直到两次FAST间隔大于2ms。,每次清理耗时不能超过1ms
  • 首先逐个遍历db,每次取20个key检查并清理过期key
  • 如果时间未达到25ms且刚才检查的过期key比例超过10%,再取20个key检查并清理。

二、淘汰策略

淘汰策略就是Redis内存使用达到阈值时,主动挑选部分key删除以释放内存。

淘汰策略在主线程解析命令后处理命令前执行,配置maxmemory-policy

  • noeviction:不淘汰任何key,内存满时不允许写入新数据,默认策略
  • volatile-ttl:对设置了TTL的key淘汰,TTL越小越先被淘汰
  • allkeys-random:对全体key(dict哈希表),随机淘汰。
  • volatile-random:对设置了TTL的key(expires哈希表),随机淘汰。
  • allkeys-lru:对全体key(dict哈希表),使用LRU算法进行淘汰。
  • volatile-lru:对设置了TTL的key(expires哈希表),使用LRU算法进行淘汰。
  • allkeys-lfu:对全体key(dict哈希表),使用LFU算法进行淘汰。
  • volatile-lfu:对设置了TTL的key(expires哈希表),使用LFU算法进行淘汰。

LRU:当前时间减最近一次访问时间,值越大优先淘汰。

LFU:访问次数越少优先淘汰。

key的访问次数和访问时间都会封装在redisObject对象中:ptr指向key-value具体值

逻辑访问次数:由于8bit只能记录实际访问次数0~255,对于热key来说远远不够,所以使用逻辑访问次数

  1. key被访问时,生成一个0~1之间的随机数R
  2. 计算P=1/(旧访问次数*10+1)
  3. 如果R<P,计数器+1,最大不超过255
  4. 为了防止key长时间不访问但访问次数一直不变,访问次数随时间衰减,距离上一次访问间隔每隔1分钟计数器-1

也就是说逻辑访问次数越大,P越小,R<P的概率越小,计数器越难+1

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Python Redis如何执行Lua脚本

    Python Redis如何执行Lua脚本

    这篇文章主要介绍了Python Redis如何执行Lua脚本问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • Redis6.2.6生产环境redis.conf单机配置

    Redis6.2.6生产环境redis.conf单机配置

    在实际生产环境中,为了保障 Redis 的稳定性和高性能,我们往往需要对默认配置进行一系列优化,本文主要介绍了Redis6.2.6生产环境redis.conf单机配置,感兴趣的可以了解一下
    2025-04-04
  • 解读缓存db redis local的取舍之道

    解读缓存db redis local的取舍之道

    这篇文章主要介绍了解读缓存db redis local的取舍之道,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • Redis6 主从复制及哨兵机制的实现

    Redis6 主从复制及哨兵机制的实现

    本文主要介绍了Redis6 主从复制及哨兵机制的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Redis的持久化方式

    Redis的持久化方式

    Redis提供了两种主要的持久化方式:RDB和AOF,RDB通过定时快照的方式保存数据状态,而AOF记录每个写操作以便于重启时重放,两者可以结合使用,且在重启时AOF文件会被优先用于数据恢复,RDB快照具有速度快、节省磁盘空间的优点,但可能会丢失最近的数据
    2024-10-10
  • redis分布式锁的go-redis实现方法详解

    redis分布式锁的go-redis实现方法详解

    这篇文章主要介绍了redis分布式锁的go-redis实现方法,本文给大家介绍的非常详细对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • 缓存替换策略及应用(以Redis、InnoDB为例)

    缓存替换策略及应用(以Redis、InnoDB为例)

    本文以Redis、InnoDB为例给大家讲解缓存替换策略及应用,本文给大家提到五种置换策略,通过实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2021-07-07
  • Redis 数值范围查询(Numeric Range Queries)的实现

    Redis 数值范围查询(Numeric Range Queries)的实现

    本文主要介绍了Redis 数值范围查询(Numeric Range Queries)的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-11-11
  • Redis与缓存解读

    Redis与缓存解读

    文章介绍了Redis作为缓存层的优势和缺点,并分析了六种缓存更新策略,包括超时剔除、先删缓存再更新数据库、旁路缓存、先更新数据库再删缓存、先更新数据库再更新缓存、读写穿透和异步缓存写入模式,还讨论了缓存常见问题
    2025-01-01
  • Redis字符串String操作详解从基础到高级应用小结

    Redis字符串String操作详解从基础到高级应用小结

    本文全面解析Redis字符串类型,涵盖设置、修改、数字运算、过期处理及分布式锁、计数器等高级应用,提供基础命令与性能优化策略,助开发者高效利用这一核心数据类型实现缓存、统计等功能,感兴趣的朋友一起看看吧
    2025-07-07

最新评论