bigywater.tech
Redis · 116

Redis Big Key 扫描

大 key 会拖慢删除、迁移、复制,得先找到它们。找的时候不能反过来把线上服务拖慢。这篇手写一个大 key 扫描器(SCAN + MEMORY USAGE),在一个埋了 5 个大 key 的库里量它:能不能找全、要多久、对其它请求有多大影响。

416k key/秒
SCAN + MEMORY USAGE 管道扫描的速度(全库 0.72 s)
2.4 ms
扫描期间另一个连接 PING 的最大停顿
5 / 5
埋入的大 key 被找出的个数

MEMORY USAGE

实测 · 本机执行输出
key          类型           元素数    MEMORY USAGE 字节     SAMPLES 默认(5)耗时 µs    SAMPLES 0 耗时 µs   SAMPLES 5 结果
big:string   string   5242880            5259293                     95                 94        5259293
big:list     list      200000            1700350                    109                103        1700350
big:hash     hash      100000            5450727                    103                104        5450727
big:set      set       150000            6784700                    105                 97        6784700
big:zset     zset       50000            4254435                    105                103        4254435

MEMORY USAGE key 返回 key 及其值占用的字节数。按字节排序和按元素个数排序结论不同:字节最多的是 15 万成员的 set(6.78 MB),元素最多的是 5 MB 字符串。所以只看元素数会漏掉「元素少但每个很大」的 key。每次调用约 0.1 ms;SAMPLES 0(理论上是精确遍历)在这些数据上耗时和默认值一样、结果完全相同——这与文档里对 SAMPLES 的说明不一致,我没有追究原因。

自己写扫描器

实测 · 本机执行输出
  扫描 300006 个 key 用了 0.72 s(416k key/秒);期间另一个连接 PING 最大停顿 2.40 ms;超过 100 KB 的 key: [('big:set', 6784700), ('big:hash', 5450727), ('big:string', 5259293), ('big:zset', 4254435), ('big:list', 1700350)]

SCAN 分批取 key(COUNT 1000),每批用管道发 MEMORY USAGE,把超过阈值(100 KB)的记下来。300006 个 key 扫描 0.72 s,PING 最大停顿只有 2.4 ms;5 个大 key 一个不漏。这是本机、小 key 为主的库;key 数更多、单批里有大 key(MEMORY USAGE 变慢)时要相应加大批与批之间的间隔。

DEBUG OBJECT

实测 · 本机执行输出
  big:list: Value at:0x76c2c2e940 refcount:1 encoding:quicklist serializedlength:776101 lru:12323709 lru_seconds_idle:1 ql_nodes:207 ql_avg_node:966.18 ql_listpack_max:-2 ql_compressed:0 ql_uncompressed_size:1690339
  big:hash: Value at:0x76c2c2e840 refcount:1 encoding:hashtable serializedlength:1877785 lru:12323709 lru_seconds_idle:1

DEBUG OBJECT(需要 enable-debug-command)给出编码、引用计数、serializedlength(RDB 序列化后的长度)等。serializedlength 与 MEMORY USAGE 口径不同:big:list 是 776101 对 1700350。

分步演示:找出 5 个大 key

Redis Big Key 扫描
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Redis 8.10.2 独立实例(本机回环端口,save 关闭),redis-cli 风格输出由自写的 RESP 客户端打印;计时用 time.perf_counter,数字每次运行会有小幅抖动。5 个大 key 是我构造的;MEMORY USAGE 用默认 SAMPLES;PING 每 0.5 ms 一次
    • 没有验证:集群上逐节点扫描、key 数上亿时的耗时、MEMORY USAGE 在嵌套/压缩编码上的精度、扫描期间有写入时大 key 的变化
    京ICP备2026067502号-1京公网安备11010502063487号