Redis(4):过期、惰性/定期删除与内存淘汰策略

0 阅读2分钟

过期

由于 Redis 是内存数据库,如果 key 过期了还一直留在内存里,内存很快就会爆掉。

image.png

1. 惰性删除 (Lazy Deletion)

逻辑: 只有当你访问(GET、SET 等)这个 key 时,Redis 才会去检查它是否过期。如果过期了,就删掉它并返回空。

  • 优点: 对 CPU 友好。Redis 不会主动去扫描几百万个 key,只在你用的时候才查一下。
  • 缺点: 对内存极不友好。如果一大堆过期 key 从来没人访问,它们就会一直赖在内存里不走。

2. 定期删除 (Periodic Deletion)

逻辑: Redis 默认每秒进行 10 次(100ms 一次)采样扫描。

  • 工作流程:
    1. 从设置了过期时间的 key 中随机抽取 20 个。
    2. 删除这 20 个中已过期的。
    3. 如果过期的比例超过 25%(即 20 个里有 5 个以上过期),则重复步骤 1,继续扫描。

3. 如果内存还是满了怎么办?(内存淘汰策略)

如果“定期删除”没抽到,“惰性删除”也没碰到,内存还是塞满了,Redis 就会触发 内存淘汰策略 (Eviction Policy)

redis.confmaxmemory-policy 中配置的一些例子:

  • noeviction (默认): 别写了,报错吧。这是最稳妥但也最危险的。
  • allkeys-lru 最常用的策略。在所有 key 中,淘汰掉最近最少使用的。
  • volatile-lru 只在设置了过期时间的 key 中,淘汰掉最近最少使用的。
  • allkeys-lfu 淘汰掉使用频率最低的。
  • allkeys-random 闭着眼随便删(不推荐)。

删除

  • 逻辑层面: 一旦执行了 DEL,Redis 会立即从它的“大字典”(dict)中把这个 Key 的索引删掉。从这一刻起,你用 EXISTSGET 再也找不到它了。
  • 物理层面:
    • 如果这个 Key 很小(比如一个简单的字符串),内存会立即被标记为“空闲”,可以给新数据使用。
    • 如果这个 Key 很大(比如一个有 100 万个元素的 List),为了不阻塞主线程,Redis 可能会在后台线程异步释放这块内存(这就是 UNLINK 命令做的事情,而最新的 Redis 版本中,DEL 也可以配置成异步)。
  • 注意: 虽然 Redis 释放了内存,但操作系统不一定会立刻把这块物理内存收回去。这也就是为什么有时候你删了数据,用 top 命令看 Redis 占用的内存还没降下来的原因(这叫内存碎片)。