过期
由于 Redis 是内存数据库,如果 key 过期了还一直留在内存里,内存很快就会爆掉。
1. 惰性删除 (Lazy Deletion)
逻辑: 只有当你访问(GET、SET 等)这个 key 时,Redis 才会去检查它是否过期。如果过期了,就删掉它并返回空。
- 优点: 对 CPU 友好。Redis 不会主动去扫描几百万个 key,只在你用的时候才查一下。
- 缺点: 对内存极不友好。如果一大堆过期 key 从来没人访问,它们就会一直赖在内存里不走。
2. 定期删除 (Periodic Deletion)
逻辑: Redis 默认每秒进行 10 次(100ms 一次)采样扫描。
- 工作流程:
- 从设置了过期时间的 key 中随机抽取 20 个。
- 删除这 20 个中已过期的。
- 如果过期的比例超过 25%(即 20 个里有 5 个以上过期),则重复步骤 1,继续扫描。
3. 如果内存还是满了怎么办?(内存淘汰策略)
如果“定期删除”没抽到,“惰性删除”也没碰到,内存还是塞满了,Redis 就会触发 内存淘汰策略 (Eviction Policy)。
redis.conf 的 maxmemory-policy 中配置的一些例子:
noeviction(默认): 别写了,报错吧。这是最稳妥但也最危险的。allkeys-lru: 最常用的策略。在所有 key 中,淘汰掉最近最少使用的。volatile-lru: 只在设置了过期时间的 key 中,淘汰掉最近最少使用的。allkeys-lfu: 淘汰掉使用频率最低的。allkeys-random: 闭着眼随便删(不推荐)。
删除
- 逻辑层面: 一旦执行了
DEL,Redis 会立即从它的“大字典”(dict)中把这个 Key 的索引删掉。从这一刻起,你用EXISTS或GET再也找不到它了。 - 物理层面:
- 如果这个 Key 很小(比如一个简单的字符串),内存会立即被标记为“空闲”,可以给新数据使用。
- 如果这个 Key 很大(比如一个有 100 万个元素的 List),为了不阻塞主线程,Redis 可能会在后台线程异步释放这块内存(这就是
UNLINK命令做的事情,而最新的 Redis 版本中,DEL也可以配置成异步)。
- 注意: 虽然 Redis 释放了内存,但操作系统不一定会立刻把这块物理内存收回去。这也就是为什么有时候你删了数据,用
top命令看 Redis 占用的内存还没降下来的原因(这叫内存碎片)。