redis的内存回收主要做了两件事情,一件是删除到达过期时间的键对象,另一件是内存到达配置的上限时触发的内存溢出控制。
过期键删除
如果redis严格按照过期时间来删除过期键会导致消耗大量的CPU,这对于单线程的redis来说成本过高,因此redis使用惰性删除和定时删除机制来回收过期键的内存
惰性删除
客户端查询带有过期属性的key时,先判断如果超过过期时间就执行删除并返回空,这样可以节省CPU开销,但是单独使用这种过期键删除方式存在内存泄露问题。如果过期键一直没被访问,那内存将无法得到释放。因此redis还提供定时任务删除过期键作为惰性删除的补充。
定时删除
- 定时随机抽取20个键,当发现抽取键的过期数没超过25%,则不执行删除
- 若过期键比例超过25%,循环执行回收逻辑直到低于25%或运行超时为止,慢模式下超时时间是25毫秒。
- 如果键回收逻辑执行超时则切换到快模式回收过期键
- 快模式与慢模式回收逻辑一致,只是执行时间不同
内存溢出控制策略
redis所用内存达到配置的上限时会触发内存溢出控制策略,可通过配置来指定触发的策略,redis提供了6种策略
- 默认不会删除任务数据,但会拒绝所有写入操作并返回客户端错误信息,只支持读操作
- 删除超时键,直到腾出足够空间为止
- 不管数据有没有超时,删除键直到腾出足够空间
- 随机删除过期键,直到腾出足够空间
内存回收时查找回收键和删除键的开销很大,集群模式下,删除命令会同步到从节点,导致写放大问题,在需要收缩redis内存的场景,调小maxmemory可以实现快速回收内存。