登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  Redis

Redis BigKeys 怎么用 MEMORY USAGE 和 SCAN 分阶段处理

来源:17golang原创

时间:2026-09-07 13:39:41 188浏览 收藏

Redis BigKeys 不适合直接用 KEYS * 一次性找完。更稳的做法是先用 SCAN 增量遍历键空间,再对候选键执行 MEMORY USAGE,最后按固定批次处理。这样既能看到键和值在 RAM 中的大致占用,也能把扫描、估算和删除拆成可暂停的几个阶段。

要点速览
  • SCANCOUNT 只是工作量提示,不能当成每次固定返回数量。
  • 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。不存在的键会返回空值,所以扫描和测量之间要接受键被淘汰、过期或被业务删除的情况。

Redis SCAN 键空间、候选键队列与 MEMORY USAGE 测量边界关系图
图1:SCAN 负责增量发现,候选键队列把结果交给 MEMORY USAGE;两者之间是可暂停的测量边界。

SAMPLES 不是精确值:先分层估算再做决定

MEMORY USAGE 统计的是键和值所需的内存,同时包含管理开销,因此它不是业务字段长度的简单相加。对嵌套或聚合数据,Redis 默认只采样一部分元素并据此估算总量;SAMPLES 0 才会采样全部元素,但成本也可能随对象规模上升。

对象情况建议读法判断重点
普通 StringMEMORY 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 

UNLINKDEL 都会移除指定键,但 UNLINK 把实际内存回收放到另一个线程,适合对象较大且不能接受长时间同步回收的场景。它并不替代备份、权限检查和业务确认;集群环境还要按节点和多键操作规则拆分。处理后再次用 SCAN 或针对性检查确认键已不在 keyspace,并观察内存回收是否滞后。

Redis 大键复核队列、批量上限、UNLINK 和异步内存回收的静态关系图
图2:确认队列先经过批量上限和业务允许删除边界,再连接到 UNLINK 与异步内存回收。

常见问题

SCAN 的 COUNT 设置越大越好吗?

不是。COUNT 只是提示,数值越大通常单次工作量越高;应结合实例延迟和业务低峰逐步调整,而不是追求一次返回更多键。

MEMORY USAGE 的结果能直接当作精确账单吗?

不能。它包含管理开销,聚合类型还可能使用采样估算。要比较趋势,应保持采样参数、筛选范围和观察窗口一致。

为什么不直接用 DEL 删除 BigKey?

DEL 的回收工作可能同步发生。对已确认可以删除的大对象,UNLINK 通常更适合分离 keyspace 操作与实际回收,但仍需关注后台回收带来的内存变化。

参考:Redis SCAN 命令文档Redis MEMORY USAGE 命令文档Redis UNLINK 命令文档

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>