UNLINK不能解决所有大Key删除抖动,因其仅异步释放内存,而元数据遍历、结构拆解、子元素标记仍阻塞主线程;Hash或嵌套ZSet等大Key触发时,仍会导致10–30ms延迟尖峰。

UNLINK 为什么不能解决所有大Key删除抖动
UNLINK 确实把 DEL 的同步释放逻辑移到后台线程,但它的“异步”只覆盖内存释放阶段;而大 Key 删除前的**元数据遍历、编码结构拆解、子元素逐个标记**仍发生在主线程。当 Key 是含 50 万成员的 Hash 或深度嵌套的 ZSet,UNLINK 启动瞬间仍会明显卡住事件循环,表现为 redis-cli --latency 出现 10–30ms 尖峰、INFO stats 中 evicted_keys 或 expired_keys 突增。
手动分批删除前必须确认的三件事
盲目分批反而放大风险。执行前先运行:
-
TYPE your:key—— 确认类型,List和Set分批逻辑完全不同 -
OBJECT ENCODING your:key—— 若返回ziplist,说明数据未触发升级,用LPOP/SPOP会意外转成linkedlist或hashtable,增大内存开销 -
MEMORY USAGE your:key—— 实际占用超 5MB 时,单次扫描 1000 个元素仍可能超 20ms,需压测调低批次(如改用 200)
按数据类型选分批命令与安全阈值
没有通用“每次删 1000”的安全值,必须匹配结构特征:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
-
String:直接UNLINK即可,无需分批;若已用SET存了 JSON 大文本,优先走业务层拆分,而非现场分批 -
Hash:用HSCAN your:key cursor COUNT 500迭代,每次拿到 key 列表后批量HDEL your:key k1 k2 ...;COUNT 超过 1000 易触发哈希表 rehash 阻塞 -
List:禁用LTRIM(它要重写整个底层链表),改用LPOP或RPOP循环,单次最多 100 个;注意LLEN对超长 List 本身就会慢 -
Set/ZSet:用SSCAN/ZSCAN+SREM/ZREM,COUNT 设为 200;若发现OBJECT ENCODING是intset,说明全是整数,可放心提到 500
分批脚本必须带熔断和游标持久化
线上跑分批脚本最怕中断后无法续跑或误删。关键点:
- 每次 SCAN 后立即用
SET my:cleanup:cursor:your:key new_cursor EX 3600持久化游标,避免实例重启丢失进度 - 在循环内加
INFO stats检查:used_cpu_sys> 0.8 或instantaneous_ops_per_sec - 用
EXISTS your:key包裹每轮操作,防止 Key 在中途被其他流程删掉导致 SCAN 报错
真正难的不是“怎么删”,而是判断删到哪一步该停——大 Key 往往是业务数据异常堆积的结果,删完立刻复现才是常态。盯着 SLOWLOG GET 10 和 redis-cli --bigkeys 周期巡检,比写完美脚本重要得多。

















