陈默的笔记

Redis 大 key 的一次线上事故

· 事故复盘

上个月某天下午,监控突然报警:从库延迟飙到 40 秒。业务侧表现是「读到的数据偶尔是旧的」,持续了大概二十分钟。

现象

看起来像是主库在往从库刷大量数据,但对外的 QPS 又没涨。

找到大 key

redis-cli --bigkeys

扫出来一个 hash,user:profile:cache:all,单个 key 里有 47 万个 field,占内存快 2GB。

代码里是这么写的:启动时把全量用户资料加载进一个 hash,方便「一次查询」。随着用户增长,这个 key 越来越大,而某次发布触发了全量重建——一次写入 2GB 的 key,主库得慢慢同步给从库,直接堵住了复制流。

为什么平时没事

平时只做增量更新,每次写几十个 field,复制没问题。只有重启/重建时才全量写一次,所以问题藏了很久,直到那天滚动发布把它暴露出来。

怎么处理的

  1. 先把重建逻辑停掉,改成从旧 key 逐批迁移
  2. 按用户 id 前缀拆成 64 个 hash:user:profile:cache:{shard}
  3. 加了写入保护:单次批量写超过 1000 个 field 就分批 + sleep

教训

顺带说一句,--bigkeys 是 SCAN 实现的,对线上影响可控,但别在高峰期跑。