Redis内存淘汰与持久化必须协同配置;volatile-lru在过期键堆积时易误删健康数据,建议改用volatile-ttl;RDB/AOF重写不清理运行时过期键;hz值影响过期键清理效率,需权衡CPU开销与清理延迟。

Redis 内存淘汰策略和持久化策略不是互斥选项,而是必须协同配置的两套机制;单靠其中一种无法解决内存压力、数据安全与性能之间的三角矛盾。
volatile-lru 为什么在混合场景下容易误伤健康数据
当大量键设置了 EXPIRE,但因定期删除不及时或惰性删除未触发,导致大量“逻辑过期但物理未删”的键堆积在内存中——此时 volatile-lru 会把这些键纳入淘汰候选池。问题在于:这些键虽然已过期,但 TTL 返回负数前仍占用内存,且 OBJECT IDLETIME 可能显示极小值(因最近被惰性检查过),结果反被当成“活跃但冷门”键提前淘汰,而真正该保留的未设过期时间的热点数据却毫发无损。
- 实际现象:
INFO keyspace显示expires=12000,但used_memory持续接近maxmemory,evicted_keys上升,业务却反馈缓存命中率骤降 - 根本原因:
volatile-lru不区分“已过期”和“未过期但长期未访问”,只看lru字段时间戳 - 建议动作:若业务大量使用过期键,优先改用
volatile-ttl;它按剩余 TTL 升序淘汰,更贴近“先过期先走”的直觉,也避免误删刚被检查过的过期键
RDB/AOF 重写时的隐式清理效果不可依赖
BGREWRITEAOF 或 BGSAVE 过程中,Redis 会扫描全量键空间,并跳过已过期键——这看起来像一次强制清理。但要注意:这只是生成快照/日志时的过滤行为,**不修改运行时内存状态**。那些没被惰性或定期删除机制触达的过期键,仍留在内存里,继续参与淘汰计算、占用 used_memory,甚至可能被 allkeys-lfu 统计为“低频访问”而保留更久。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 典型误判:看到 AOF rewrite 后
rdb_last_bgsave_status:ok就认为过期键已清空 - 验证方式:执行
INFO memory后比对mem_clients_normal和mem_clients_slave差值,再结合INFO keyspace的expires数量交叉判断 - 真实影响:AOF rewrite 虽然压缩了日志体积,但若内存中过期键堆积严重,fork 子进程时 copy-on-write 开销反而更大,
latest_fork_usec可能飙升
hz 配置值直接影响过期键清理节奏与淘汰策略压力
redis.conf 中的 hz 参数控制后台定期删除线程的执行频率,默认是 10。它不是“每秒删多少键”,而是“每秒最多尝试多少轮抽查”。每轮随机抽 20 个带过期时间的键,若超 25% 过期则立即再抽一轮——这意味着 hz=10 理论上每秒最多检查 200 个键,但在高并发、大批量集中过期场景下,这个速度远远不够。
- 后果:过期键积压 →
used_memory虚高 → 提前触发maxmemory-policy→ 淘汰本不该淘汰的键 - 调优边界:
hz设为 100 时,CPU 使用率可能上升 3%~5%,但expires清理延迟从分钟级降到秒级;线上建议先试 50,观察expired_keys增速和latest_fork_usec - 注意陷阱:单纯提高
hz不能解决惰性删除缺失的问题;若业务读请求极少(如纯写入型缓存),仍需配合volatile-ttl或主动SCAN+DEL清理
最常被忽略的一点:淘汰策略决策发生在内存分配前的毫秒级窗口,而持久化文件里的键状态永远滞后于运行时。你永远无法靠 dump.rdb 或 appendonly.aof 的内容去推测当前哪些键正被 allkeys-lru 考量——它们只反映某个过去时刻的快照,而非此刻内存的真实负载结构。

















