Redis 大键怎么用 MEMORY USAGE 和抽样扫描定位
来源:17golang原创
时间:2026-09-08 09:48:45 288浏览 收藏
Redis 出现内存上涨时,先不要直接执行 KEYS * 或凭键名猜“大键”。更稳妥的做法是:用 SCAN 按游标分批枚举目标命名空间,再对候选键调用 MEMORY USAGE 比较字节数;只有进入候选集的聚合类型,才考虑提高 SAMPLES 精度。这样既能定位单键占用,也不会把单键问题和实例碎片率混为一谈。
SCAN的COUNT只是工作量提示,游标返回0才代表一轮遍历结束,结果可能包含重复键。MEMORY USAGE统计键、值和管理开销;聚合类型默认抽样 5 个嵌套元素,SAMPLES 0才会采样全部。- 发现大键后先确认数据类型、元素数量和访问模型,再决定拆分、限长或清理,不能只看一个字节数就删除。
先用 SCAN 找到值得测量的候选键
SCAN cursor [MATCH pattern] [COUNT count] [TYPE type] 是增量式键空间迭代。第一次把游标设为 0,之后持续使用 Redis 返回的新游标,直到再次得到 0。MATCH 适合限定业务前缀,TYPE 可以缩小到某种数据类型,COUNT 只影响每次调用的工作量提示,并不保证返回固定数量。
| 参数 | 作用 | 排查时的判断 |
|---|---|---|
| cursor | 保存迭代位置 | 返回 0 才完成一轮 |
| MATCH | 按 glob 模式筛选键名 | 优先限制业务前缀 |
| COUNT | 每次调用的工作量提示 | 不是固定返回条数 |
| TYPE | 按 Redis 数据类型过滤 | 缩小候选范围,不代表内存大小 |
下面的命令只演示“收集候选键”,没有把结果当成大键结论。生产排查应选择低峰窗口,并把前缀换成真实业务命名空间:
# 中文注释:只扫描订单缓存命名空间,不使用会阻塞全库的 KEYS redis-cli --scan --pattern 'order-cache:*' --count 100 # 中文注释:按游标逐批读取某个类型,直到返回游标为 0 redis-cli SCAN 0 MATCH 'order-cache:*' COUNT 100 TYPE hash
不要因为某一批返回空数组就停止;只要游标不是 0,迭代就没有完成。键在扫描期间发生新增、删除或迁移时,完整遍历也不等价于某一时刻的严格快照;同一个键可能出现多次,所以后续统计要允许去重。

用 MEMORY USAGE 判断单键到底占了多少内存
拿到候选键后,使用 MEMORY USAGE key 读取 Redis 为该键和值分配的内存字节数,其中也包含数据结构管理开销。它回答的是“这个键在 Redis 内存里大约占多少”,不是业务字段长度,也不是整个实例的 RSS。
# 中文注释:先测单键,便于和同一命名空间的其他键比较 redis-cli MEMORY USAGE 'order-cache:20260908:001' # 中文注释:对候选键输出类型、元素数量和估算字节数 key='order-cache:20260908:001' printf 'key=%s type=%s items=%s bytes=%s\n' "$key" \ "$(redis-cli TYPE "$key")" \ "$(redis-cli HLEN "$key" 2>/dev/null || true)" \ "$(redis-cli MEMORY USAGE "$key")"
对于 string,长度和编码通常足以帮助解释结果;对于 hash、list、set、zset 等聚合类型,默认 SAMPLES 5 是估算路径,不应把它误读成“只统计了五个元素”。如果只需要先排序找候选,默认值通常更合适,因为每次测量的工作量更低。

只对候选大键增加抽样精度
当某个 hash 或 zset 明显高于同类键,再用 SAMPLES 0 做复核,表示采样全部嵌套元素。它的复杂度随采样数量增长,不适合对整个键空间里的每个聚合键无差别调用:
# 中文注释:只对已入选的聚合键读取更完整的内存估算 key='order-cache:20260908:001' type=$(redis-cli TYPE "$key") bytes=$(redis-cli MEMORY USAGE "$key" SAMPLES 0) printf 'candidate=%s type=%s bytes=%s\n' "$key" "$type" "$bytes" # 中文注释:用类型专属命令确认膨胀来自元素数量还是单个值过大 redis-cli HLEN "$key" # 中文注释:hash 关注字段数量 redis-cli MEMORY USAGE "$key" SAMPLES 0
“大”没有脱离业务的统一阈值:一个低频 hash 可能值得拆分,一个高频小 hash 也可能因访问路径不当拖慢请求。建议把结果和同前缀键的分位数、访问频率、TTL、元素数量一起记录,再决定是否拆分对象、限制列表长度或调整缓存粒度。
把大键、碎片率和处理动作分开判断
单键占用高,说明数据模型或某个值可能膨胀;实例的 mem_fragmentation_ratio 偏高,则说明分配器与进程常驻内存之间存在额外空间,二者不是同一证据。可以补看:
# 中文注释:读取实例级内存指标,和单键 MEMORY USAGE 分开记录 redis-cli INFO memory | grep -E 'used_memory:|used_memory_rss:|mem_fragmentation_ratio:'
如果大键集中在同一种业务对象,优先从写入侧限制字段数、单值长度或集合增长速度;如果单键并不突出但碎片率持续异常,再独立评估分配器、重启窗口和实例容量。任何删除或拆分动作都要先确认 TTL、回源能力和并发读写模型,先灰度一个前缀比一次性清空更可控。
常见问题
SCAN 能不能完全替代 KEYS?
在生产排查键空间时通常应优先用 SCAN,因为它分批返回、单次调用成本更可控;但它不是严格快照,仍需处理重复键和扫描期间的键变化。
MEMORY USAGE 为什么和字符串长度不一样?
它统计的是 Redis 在内存中的分配,除了值本身还包括键、编码和管理开销;短字符串也可能有明显的固定开销。
SAMPLES 0 是不是越精确越应该默认使用?
不是。SAMPLES 0 会扩大聚合类型的测量工作量,适合对少量候选大键复核;全库粗筛先用默认抽样,再针对候选加精度更稳妥。
需要查参数细节时,可直接参考 Redis 官方的 SCAN 命令文档 和 MEMORY USAGE 命令文档,再按目标实例版本和客户端实现调整命令。
-
423 收藏
-
377 收藏
-
154 收藏
-
501 收藏
-
104 收藏
-
114 收藏
-
数据库 · Redis | 8小时前 | 消息队列 · 消费组 · Redis Streams · 故障接管 · redis streams 消费组 XREADGROUP XACK XPENDING XAUTOCLAIM192 收藏
-
408 收藏
-
279 收藏
-
325 收藏
-
460 收藏
-
480 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习