Redis BigKeys 怎么用 MEMORY USAGE 和 SCAN 分阶段处理
来源:17golang原创
时间:2026-09-07 13:39:41 188浏览 收藏
Redis BigKeys 不适合直接用 KEYS * 一次性找完。更稳的做法是先用 SCAN 增量遍历键空间,再对候选键执行 MEMORY USAGE,最后按固定批次处理。这样既能看到键和值在 RAM 中的大致占用,也能把扫描、估算和删除拆成可暂停的几个阶段。
SCAN的COUNT只是工作量提示,不能当成每次固定返回数量。MEMORY USAGE返回字节数;聚合类型的默认采样是估算,必要时再使用SAMPLES 0。- 删除大键前先确认业务语义,批量解除链接优先考虑
UNLINK,并记录每批结果。
先用 SCAN 找键,再用 MEMORY USAGE 定位大键
SCAN 0 开始一次全量迭代,服务端返回新的游标和一批键;把新游标继续传回去,直到游标回到 0。它的优势是把遍历拆成多次调用,适合生产环境做低冲击巡检。MATCH 可以限制前缀,COUNT 可以提示每次多做一些工作,但两者都不能保证每次正好拿到同样数量的键。
# 只扫描订单缓存前缀,游标回到 0 才表示本轮结束 cursor=0 while :; do reply=$(redis-cli --raw SCAN "$cursor" MATCH 'order:cache:*' COUNT 200) cursor=$(printf '%s\n' "$reply" | sed -n '1p') printf '%s\n' "$reply" | sed -n '2,$p' # 后续行是本批键名 [ "$cursor" = "0" ] && break done
实际测量时不要把所有返回键积存在内存里。可以边读边把键送入测量队列,或者每批保存几百个键。接着对候选执行 MEMORY USAGE key。不存在的键会返回空值,所以扫描和测量之间要接受键被淘汰、过期或被业务删除的情况。

SAMPLES 不是精确值:先分层估算再做决定
MEMORY USAGE 统计的是键和值所需的内存,同时包含管理开销,因此它不是业务字段长度的简单相加。对嵌套或聚合数据,Redis 默认只采样一部分元素并据此估算总量;SAMPLES 0 才会采样全部元素,但成本也可能随对象规模上升。
| 对象情况 | 建议读法 | 判断重点 |
|---|---|---|
| 普通 String | MEMORY USAGE key | 注意键名、值和分配器开销 |
| 较大的 Hash/List/Set/ZSet | 先默认采样,重点对象再用 SAMPLES 0 | 估算值与元素数量都要记录 |
| 键可能已失效 | 把空返回当作“本轮跳过” | 不要把它计入总内存 |
因此“大键阈值”应当是业务巡检策略,而不是 Redis 命令的内置结论。例如先把超过 10 MB 的键进入复核队列,再按数据类型和 TTL 分组;对短 TTL 的临时缓存,处理优先级可能低于长期存在且持续增长的集合。扫描报告至少保留键名、类型、字节数、TTL、采样参数和观察时间。
处理时按小批次取样,删除优先考虑 UNLINK
发现大键不等于可以马上删除。先确认它是可重建缓存、过期队列还是仍被业务读取的数据。对可删除对象,按前缀和风险分组,每批设置明确数量;批次之间留出观察窗口,避免把扫描压力和业务删除压力叠加。
# 只对已确认可删除的键分批解除链接,批量大小由现场压测决定
batch_size=50
batch=()
while IFS= read -r key; do
batch+=("$key")
if [ "${#batch[@]}" -ge "$batch_size" ]; then
redis-cli UNLINK "${batch[@]}" # 先从 keyspace 解除链接,回收异步进行
batch=()
fi
done
UNLINK 和 DEL 都会移除指定键,但 UNLINK 把实际内存回收放到另一个线程,适合对象较大且不能接受长时间同步回收的场景。它并不替代备份、权限检查和业务确认;集群环境还要按节点和多键操作规则拆分。处理后再次用 SCAN 或针对性检查确认键已不在 keyspace,并观察内存回收是否滞后。

常见问题
SCAN 的 COUNT 设置越大越好吗?
不是。COUNT 只是提示,数值越大通常单次工作量越高;应结合实例延迟和业务低峰逐步调整,而不是追求一次返回更多键。
MEMORY USAGE 的结果能直接当作精确账单吗?
不能。它包含管理开销,聚合类型还可能使用采样估算。要比较趋势,应保持采样参数、筛选范围和观察窗口一致。
为什么不直接用 DEL 删除 BigKey?
DEL 的回收工作可能同步发生。对已确认可以删除的大对象,UNLINK 通常更适合分离 keyspace 操作与实际回收,但仍需关注后台回收带来的内存变化。
参考:Redis SCAN 命令文档、Redis MEMORY USAGE 命令文档、Redis UNLINK 命令文档。
-
392 收藏
-
Golang · Go教程 | 2个月前 | channel · select · Context · Go教程 · 性能排查 · select channel context default time.Ticker Go教程 CPU飙高 for select459 收藏
-
395 收藏
-
Golang · Go教程 | 1个月前 | golang · Timer · 并发编程 · time.After · 性能排查 · time.After go timer Go 1.23 NewTimer Timer.Reset Timer.Stop403 收藏
-
Golang · Go教程 | 1个月前 | 并发 · go · trace · 性能排查 · Go 1.25 · Go 1.25 runtime/trace FlightRecorder 运行时追踪 延迟排查425 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习