Redis的数据过期淘汰策略
Redis 的数据过期策略
Redis 采用 「惰性删除 + 定期删除」 两种策略相结合的方式,在 CPU 性能开销 与 内存占用 之间取得平衡。
一、惰性删除(Lazy Expiration)
当客户端访问或修改某个键时,Redis 会在操作前调用 expireIfNeeded() 函数检查该键是否已过期:
- 若已过期:
Redis 会立即删除该键,然后向客户端返回null。
删除方式由配置项lazyfree-lazy-expire决定:- 若开启(
yes),则采用 异步删除; - 若关闭(
no),则采用 同步删除。
- 若开启(
- 若未过期:
直接返回该键对应的正常值,不做任何额外处理。
这种方式的优点是 删除时机精准、不会浪费 CPU 时间;
缺点是:若某些过期键一直未被访问,就无法被清除,会长期占用内存。
二、定期删除(Active Expiration Cycle)
为了解决惰性删除的不足,Redis 还会周期性地扫描部分键空间,清除已过期的数据。
1. 检查频率
Redis 默认每秒执行 10 次过期扫描,这一频率由配置文件 redis.conf 中的参数 hz 控制:
1 | hz 10 |
即 Redis 每隔约 100 毫秒 触发一次过期检测。
2. 检查机制
Redis 并不会遍历所有键,而是采用「随机抽查」机制来控制 CPU 占用。
该逻辑由 expire.c 文件中的 activeExpireCycle() 函数实现,核心过程如下:
- 从每个数据库的「过期字典」中 随机抽取 20 个 key(数量由常量
ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP = 20决定); - 检查这 20 个 key 是否过期,并删除已过期的 key;
- 如果本轮抽查中,超过 25%(即 5 个)键过期,说明系统中可能仍存在大量过期数据,Redis 会继续重复步骤 1,进行新一轮检查;
- 若过期比例低于 25%,则认为当前负载正常,Redis 会停止本轮扫描,等待下一次周期执行。
介绍一下Redis 内存淘汰策略
在 32 位操作系统中,maxmemory 的默认值是 3G,因为 32 位的机器最大只支持 4GB 的内存,而系统本身就需要一定的内存资源来支持运行,所以 32 位操作系统限制最大 3 GB 的可用内存是非常合理的,这样可以避免因为内存不足而导致 Redis 实例崩溃。
1、不进行数据淘汰的策略:
- noeviction(Redis3.0之后,默认的内存淘汰策略) :它表示当运行内存超过最大设置内存时,不淘汰任何数据,这时如果有新的数据写入,会报错通知禁止写入,不淘汰任何数据,但是如果没用数据写入的话,只是单纯的查询或者删除操作的话,还是可以正常工作。
2、进行数据淘汰的策略:
针对「进行数据淘汰」这一类策略,又可以细分为「在设置了过期时间的数据中进行淘汰」和「在所有数据范围内进行淘汰」这两类策略。
- 在设置了过期时间的数据中进行淘汰:
- volatile-random:随机淘汰设置了过期时间的任意键值;
- volatile-ttl:优先淘汰更早过期的键值。
- volatile-lru(Redis3.0 之前,默认的内存淘汰策略):淘汰所有设置了过期时间的键值中,最久未使用的键值;
- volatile-lfu(Redis 4.0 后新增的内存淘汰策略):淘汰所有设置了过期时间的键值中,最少使用的键值;
- 在所有数据范围内进行淘汰:
- allkeys-random:随机淘汰任意键值;
- allkeys-lru:淘汰整个键值中最久未使用的键值;
- allkeys-lfu(Redis 4.0 后新增的内存淘汰策略):淘汰整个键值中最少使用的键值。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 彬子的Blog!



