三者共现即大key导致主从卡死:slave_repl_offset与master_repl_offset差值长期不缩小、net_output_bytes突增、从节点日志反复出现timeout waiting for bulk read。

怎么确认主从卡死真是大Key惹的祸
别急着删,先看三样东西是否同时出现:slave_repl_offset 和 master_repl_offset 差值长期不缩小、net_output_bytes 突增、从节点日志里反复出现 Timeout waiting for bulk read。这三者共现,基本就是某个大Key在单次复制中把通道堵死了。
redis-cli --bigkeys 只能告诉你“哪个key大”,但无法反映它正在拖垮同步流;更准的方式是:用 MEMORY USAGE bigkey_name 查真实内存占用,再配合 OBJECT FREQ bigkey_name 和 OBJECT IDLETIME bigkey_name 判断是不是冷数据——热key硬拆可能引发新抖动,冷key才值得动。
HSCAN/SSCAN 拆分大Hash或大Set时必须避开的坑
直接 HDEL 或 DEL 大Key?绝对不行。主节点CPU瞬间拉满,而且这条删除命令本身又会作为一条巨量指令同步到从节点,形成二次冲击。
- 所有操作必须在主节点执行,确保写入、删除都走复制流;从节点只读,不参与任何拆分逻辑
-
HSCAN myhash 0 COUNT 100每次最多拉 100 个 field;SSCAN myset 0 COUNT 500同理,别贪多——从节点单条命令超 500KB 就容易触发client-output-buffer-limit断连 - 每次操作后加
SLEEP 0.01(比如用redis-cli --eval调 Lua),避免连续高密度命令压垮主线程或复制缓冲区 - 新 key 命名要有规律,比如
myhash:shard001、myset:part1,方便后续清理和监控
UNLINK 真的能解决主从同步问题吗
不能。UNLINK 只是把删除任务扔给后台线程,主线程不卡了,但对从节点完全没帮助:主节点写入 AOF 和复制流的仍是 DEL 命令,从节点收到后照样得同步执行一次阻塞删除。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
所以 UNLINK 单独用,解决不了主从同步问题。它只有配合渐进式拆分才有意义——比如先用 HSCAN 把大 Hash 拆成小份,再对每个小 key 用 UNLINK 清理,这时每条删除都轻量,复制流才安全。
KEYS * 导致主节点假死,比大Key更隐蔽的雷
有次线上故障,主节点突然被哨兵判定为宕机并自动切换,查日志发现是定时任务执行了 KEYS temp_token:*,当时匹配出 40 多万个 key,耗时 3.8 秒,直接卡死主线程,哨兵心跳断连。
这种场景比大Key更难察觉,因为不是某个 key 大,而是遍历动作本身阻塞了整个服务:
- 永远用
SCAN替代KEYS,配COUNT限流,比如SCAN 0 MATCH temp_token:* COUNT 200 - 批量删除时,每批控制在 200–500 个 key,删完加
SLEEP 0.01 - 最根本的是:写入时就设 TTL,比如
SET temp_token:abc xxx EX 1800,让 Redis 自己回收,避免堆积
真正棘手的从来不是“怎么删”,而是“删之前有没有意识到它正在同步流里当堰塞湖”——大Key的影响是延迟暴露的,等 slave_repl_offset 差几百MB再反应,往往已经晚了。










