Redis内存淘汰是写命令实时触发的按需释放机制:每次写操作前检查used_memory是否超maxmemory,超限则循环执行“选key→删除→更新统计→再判断”,直至满足条件,不预估、不批量清理。

Redis 内存淘汰不是靠定时扫描或后台线程主动清理,而是由写命令「实时触发 + 按需释放」——它不预估、不批量预留,只在每次写操作前检查内存是否超限,超了就现场删,直到腾出足够空间才执行该写命令。所谓“精准计算”,其实是「目标导向的渐进式释放」:不是算清要删多少字节,而是删到 used_memory ≤ maxmemory 为止。
淘汰触发的精确判断条件
Redis 每次执行写命令(如 SET、LPUSH、HSET、INCR)时,会立即调用内存检查逻辑:
- 读取当前
used_memory(实际已用内存,含数据、元数据、客户端缓冲等) - 对比配置的
maxmemory值(单位字节,0 表示不限制) - 若
used_memory > maxmemory,立刻进入淘汰循环;否则直接执行命令
注意:GET、EXISTS 等纯读命令完全不触发淘汰,也不参与内存判定。
释放内存的执行方式:边删边测,非一次性清空
淘汰不是“算好删 512KB 就停”,而是反复执行「选 key → 删除 → 更新内存统计 → 再判断」,直到满足条件。整个过程在单次写命令的上下文中同步完成:
- 每次从候选集里按策略选出一个 key(例如
allkeys-lru从所有 key 中挑最久未使用的) - 立即释放该 key 占用的全部内存(包括 value、过期时间结构、编码开销等)
- 更新
used_memory统计值(Redis 内部维护精确的内存计数器) - 再次比较
used_memory ≤ maxmemory;未达标则继续下一轮淘汰
这意味着:一次大 value(比如 10MB 的字符串)可能删一次就达标;而删 100 个各占 1KB 的小 key 才够,也完全可能。
为什么不能提前“精准算出要删几个”?
因为 Redis 不预先遍历、不缓存 key 的精确内存占用,而是在淘汰时才实时计算每个候选 key 的实际开销:
- value 内存 ≠
STRLEN结果,还包含 SDS 头、编码冗余、指针等 - 集合类结构(
zset、hash)内存分布不均,无法靠 key 数量估算 - LFU/LRU 近似算法只维护采样集,不记录全量访问历史,无法反推“删谁最省”
所以 Redis 选择务实路径:不预测,只反馈;不求最优解,但保底线可用。
如何观察和验证释放行为?
你可以通过以下方式确认淘汰是否发生、删了多少:
- 启用日志:
redis.conf中设置loglevel notice或更高,淘汰时会打印类似"Evicting one key: xxx" - 监控指标:
INFO memory查看mem_evicted_keys(累计淘汰 key 数)、used_memory实时变化 - 模拟测试:用
CONFIG SET maxmemory 10mb配小内存,再批量SET大 value,观察命令是否阻塞或报错(OOM command not allowed表示noeviction生效)


















