Redis maxmemory-policy 变更前怎么评估已有键的淘汰风险
来源:17golang原创
时间:2026-09-08 12:36:29 133浏览 收藏
准备把 Redis 的 maxmemory-policy 从 noeviction 改成某种自动淘汰策略时,先别急着改配置。真正要回答的是:当前实例里哪些键是可重建缓存,哪些键没有 TTL 却承载业务状态,以及内存压力到底来自数据、少数大键还是分配器保留。安全的评估顺序是先读指标,再用 SCAN 抽样,最后用 MEMORY USAGE 对大键定位;只看碎片率或只看键数量都不够。
如果 Redis 同时放缓存和持久业务键,优先把键空间按前缀、TTL 和数据类型分开统计,再决定使用allkeys-*还是volatile-*。没有 TTL 的键在volatile-*下不会自动变成合格淘汰对象。
used_memory_dataset说明数据集大小,used_memory_rss还包含进程与分配器层面的占用。SCAN用于低干扰地抽样键名;MEMORY USAGE用于定位单键或聚合值的内存大户。allkeys与volatile的风险边界不同,策略选择必须结合 TTL 覆盖率和业务键分类。
先把内存上限和真实占用分开看
先保存变更前的基线,至少包括上限、数据集、RSS、淘汰计数和命中情况。Redis 官方文档特别提醒,删除键后分配器不一定立刻把页归还操作系统,因此 used_memory_rss 偏高不等于当前数据集同样大。
# 读取上限、数据集、RSS、碎片和复制/AOF缓冲区线索
redis-cli INFO memory | grep -E 'used_memory:|used_memory_dataset:|used_memory_rss:|maxmemory:|maxmemory_policy:|mem_fragmentation_ratio:|mem_not_counted_for_evict:'
# 读取淘汰、过期和缓存命中基线
redis-cli INFO stats | grep -E 'evicted_keys:|expired_keys:|keyspace_hits:|keyspace_misses:'
# 确认当前策略,不在基线采集阶段改配置
redis-cli CONFIG GET maxmemory maxmemory-policy
判断时把 used_memory_dataset 与 maxmemory 放在一起看;把 used_memory_rss 与碎片字节数、allocator 指标放在一起看。若数据集并未逼近上限,单凭碎片率偏高就切换淘汰策略,往往是在处理错误的问题。

用 SCAN 按前缀看清键空间组成
下一步不是执行 KEYS *,而是按业务前缀做增量扫描。SCAN 的 COUNT 只是每次工作的提示,不保证每次返回固定数量;因此要以完整游标结束后的样本累计为准。下面的示例只抽取一小段缓存键,适合先判断命名和大小分布:
# 只抽样 cache: 前缀,避免一次性把全部键名拉回客户端
redis-cli --scan --pattern 'cache:*' | head -n 200 |
while IFS= read -r key; do
# 先记录类型和 TTL,判断它是否具备过期语义
type=$(redis-cli TYPE "$key")
ttl=$(redis-cli TTL "$key")
printf '%s\t%s\t%s\n' "$type" "$ttl" "$key"
done
把样本按前缀、类型和 TTL 分组。缓存键通常可以重建,但会话、幂等记录或业务状态不能因为名字里带了 cache: 就直接归类为可淘汰数据。若同一实例混合多种用途,先把持久键迁移到独立实例,通常比依赖 volatile 策略兜底更容易解释。
再用 MEMORY USAGE 找出真正的大键
键数量少不代表占用小,List、Hash、Set 和 Sorted Set 里的一个聚合值可能才是压力来源。对抽样键执行 MEMORY USAGE,返回值包含数据和管理开销;嵌套类型默认按样本估算,不能把它当作精确的业务 payload 大小。
# 对一组候选键测量占用,按字节从大到小排序
redis-cli --scan --pattern 'cache:*' | head -n 200 |
while IFS= read -r key; do
# MEMORY USAGE 返回的是该键在 Redis 中的估算字节数
bytes=$(redis-cli MEMORY USAGE "$key")
printf '%s\t%s\n' "$bytes" "$key"
done | sort -nr | head -n 20
大键清单要同时记录数据类型、TTL 和业务拥有者。大键本身不会告诉你应该用哪一种淘汰策略,它只说明某些删除动作可能释放较多空间,也可能造成更明显的缓存重建抖动。生产环境可扩大抽样范围,但要控制 SCAN 频率和 MEMORY USAGE 的调用量。
按 TTL 和键类型判断谁会进入淘汰集合
策略的关键差异在淘汰范围:allkeys-lru、allkeys-lfu 会从全部键中选择;volatile-lru、volatile-lfu 等只考虑带过期时间的键。如果没有键设置 TTL,volatile-* 的行为会接近 noeviction,这不是“策略已生效但 Redis 选错了键”,而是候选集合为空。
| 观察结果 | 优先核对 | 变更风险 |
|---|---|---|
| 缓存键几乎都有 TTL,持久键独立 | TTL 覆盖率、expired_keys、命中率 | 可评估 volatile 系列,但要防止 TTL 过短导致穿透 |
| 缓存和业务键混在同一库 | 前缀归属、无 TTL 键比例、大键清单 | allkeys 系列可能淘汰不可重建数据 |
| RSS 高而数据集未同步增长 | mem_fragmentation_bytes、allocator 指标、历史峰值 | 改淘汰策略未必降低 RSS,应先处理分配器和容量 |

最后保留一次可回退的变更记录:当前策略、目标策略、变更时间、抽样范围和回退条件。切换后继续观察 evicted_keys、命中率、延迟和应用侧缓存重建量;不要因为淘汰计数增加就立即判定失败,也不要只看 Redis 内存下降就认为业务安全。
相关问题
碎片率高到多少才必须改 maxmemory-policy?
没有脱离工作负载的单一阈值。先看碎片字节数、数据集与 RSS 的差额以及历史峰值;如果只是少量字节造成比例偏高,改淘汰策略通常无效。
可以用 DBSIZE 代替大键分析吗?
不可以。DBSIZE 只回答键数量,不能说明键值大小、类型、TTL 或管理开销;大键定位仍要用抽样后的 MEMORY USAGE。
为什么 volatile 策略没有淘汰效果?
最常见原因是候选键没有设置过期时间,或带 TTL 的键已经很少。先按前缀统计 TTL,再结合 evicted_keys 和命中率判断。
-
499 收藏
-
288 收藏
-
423 收藏
-
377 收藏
-
154 收藏
-
501 收藏
-
104 收藏
-
114 收藏
-
数据库 · Redis | 11小时前 | 消息队列 · 消费组 · Redis Streams · 故障接管 · redis streams 消费组 XREADGROUP XACK XPENDING XAUTOCLAIM192 收藏
-
408 收藏
-
279 收藏
-
325 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习