Redis原理篇:内存回收策略

📅 发布时间:2026/7/7 6:10:56 👁️ 浏览次数:
Redis原理篇:内存回收策略
Redis内存回收-过期key处理Redis之所以性能强最主要的原因就是基于内存存储。然而单节点的Redis其内存大小不宜过大会影响持久化或主从同步性能。 我们可以通过修改配置文件来设置Redis的最大内存当内存使用达到上限时就无法存储更多数据了。为了解决这个问题Redis提供了一些策略实现内存回收内存过期策略在学习Redis缓存的时候我们说过可以通过expire命令给Redis的key设置TTL存活时间可以发现当key的TTL到期以后再次访问name返回的是nil说明这个key已经不存在了对应的内存也得到释放。从而起到内存回收的目的。Redis本身是一个典型的key-value内存存储数据库因此所有的key、value都保存在之前学习过的Dict结构中。不过在其database结构体中有两个Dict一个用来记录key-value另一个用来记录key-TTL。这里有两个问题需要我们思考 Redis是如何知道一个key是否过期呢利用两个Dict分别记录key-value对及key-ttl对是不是TTL到期就立即删除了呢惰性删除惰性删除顾明思议并不是在TTL到期后就立刻删除而是在访问一个key的时候检查该key的存活时间如果已经过期才执行删除。周期删除周期删除顾明思议是通过一个定时任务周期性的抽样部分过期的key然后执行删除。执行周期有两种 Redis服务初始化函数initServer()中设置定时任务按照server.hz的频率来执行过期key清理模式为SLOW Redis的每个事件循环前会调用beforeSleep()函数执行过期key清理模式为FAST周期删除顾明思议是通过一个定时任务周期性的抽样部分过期的key然后执行删除。执行周期有两种 Redis服务初始化函数initServer()中设置定时任务按照server.hz的频率来执行过期key清理模式为SLOW Redis的每个事件循环前会调用beforeSleep()函数执行过期key清理模式为FASTSLOW模式规则执行频率受server.hz影响默认为10即每秒执行10次每个执行周期100ms。执行清理耗时不超过一次执行周期的25%.默认slow模式耗时不超过25ms逐个遍历db逐个遍历db中的bucket抽取20个key判断是否过期如果没达到时间上限25ms并且过期key比例大于10%再进行一次抽样否则结束FAST模式规则过期key比例小于10%不执行 执行频率受beforeSleep()调用频率影响但两次FAST模式间隔不低于2ms执行清理耗时不超过1ms逐个遍历db逐个遍历db中的bucket抽取20个key判断是否过期 如果没达到时间上限1ms并且过期key比例大于10%再进行一次抽样否则结束小总结RedisKey的TTL记录方式在RedisDB中通过一个Dict记录每个Key的TTL时间过期key的删除策略惰性清理每次查找key时判断是否过期如果过期则删除定期清理定期抽样部分key判断是否过期如果过期则删除。 定期清理的两种模式SLOW模式执行频率默认为10每次不超过25msFAST模式执行频率不固定但两次间隔不低于2ms每次耗时不超过1msRedis内存回收-内存淘汰策略内存淘汰就是当Redis内存使用达到设置的上限时主动挑选部分key删除以释放更多内存的流程。Redis会在处理客户端命令的方法processCommand()中尝试做内存淘汰淘汰策略Redis支持8种不同策略来选择要删除的keynoeviction 不淘汰任何key但是内存满时不允许写入新数据默认就是这种策略。volatile-ttl 对设置了TTL的key比较key的剩余TTL值TTL越小越先被淘汰allkeys-random对全体key 随机进行淘汰。也就是直接从db-dict中随机挑选volatile-random对设置了TTL的key 随机进行淘汰。也就是从db-expires中随机挑选。allkeys-lru 对全体key基于LRU算法进行淘汰volatile-lru 对设置了TTL的key基于LRU算法进行淘汰allkeys-lfu 对全体key基于LFU算法进行淘汰volatile-lfu 对设置了TTL的key基于LFI算法进行淘汰 比较容易混淆的有两个LRULeast Recently Used最少最近使用。用当前时间减去最后一次访问时间这个值越大则淘汰优先级越高。LFULeast Frequently Used最少频率使用。会统计每个key的访问频率值越小淘汰优先级越高。Redis的数据都会被封装为RedisObject结构LFU的访问次数之所以叫做逻辑访问次数是因为并不是每次key被访问都计数而是通过运算生成0~1之间的随机数R计算 (旧次数 * lfu_log_factor 1)记录为P如果 R P 则计数器 1且最大不超过255访问次数会随时间衰减距离上一次访问时间每隔 lfu_decay_time 分钟计数器 -1最后用一副图来描述当前的这个流程吧