先看内存:满没满、碎不碎
`INFO memory` 是第一站:`used_memory_human` 是实际占用,`maxmemory` 是上限(0 表示未限制——危险,会被操作系统 OOM 杀掉);`mem_fragmentation_ratio` 大于 1.5 说明碎片偏多,频繁删改大 value 的场景常见。
内存满 + 淘汰策略为 noeviction 时,写命令直接报 OOM 错误;应用层的表现往往是「偶发写失败」,容易被误判为网络问题。
redis-cli INFO memory | grep -E "used_memory_human|maxmemory_human|mem_fragmentation"
redis-cli CONFIG GET maxmemory扫描大 key:慢的常见元凶
一个包含百万成员的 ZSET,一条 ZRANGE 全量就可能耗时数秒,把后面所有命令全部排队。用 `redis-cli --bigkeys` 低开销采样各类型最大的 key;要精确体积用 `--memkeys`(需 redis 6.0+ 的扩展)或 MEMORY USAGE 逐个测量。
注意 --bigkeys 是采样,生产上可以放心跑(内部用 SCAN 游标,不阻塞);但绝对不要用 KEYS *,它一次性遍历全库,是线上事故制造机。
redis-cli --bigkeys # 采样找各类型最大 key(安全)
redis-cli MEMORY USAGE <key> # 精确测量单个 key看慢日志:哪条命令在拖后腿
Redis 内置慢日志会记录超过阈值的命令(默认 10ms,建议调到 1ms 以捕获更多线索)。`SLOWLOG GET 10` 查看最近十条,关注命令名、耗时与 key 名,再反查业务代码调用点。
高耗时命令排行榜:KEYS、SMEMBERS 大集合、HGETALL 大哈希、ZRANGE 全量、FLUSHALL/FLUSHDB、Lua 脚本里的长循环。逐个替换:KEYS → SCAN,SMEMBERS → SSCAN 分批,HGETALL → HMGET 取需要的字段。
redis-cli CONFIG SET slowlog-log-slower-than 1000 # 阈值降到 1ms
redis-cli SLOWLOG GET 10淘汰策略:内存满之后的行为开关
缓存场景选 allkeys-lru(全库 LRU 淘汰)或 allkeys-lfu(热点更准,4.0+);存数据必须持久保留的场景选 noeviction,但必须提前扩容并加告警,否则写失败只是时间问题。volatile-* 系列只淘汰设置了过期时间的 key——如果业务没设 TTL,等于变相 noeviction。
改完策略立即验证:压一轮写入确认不再报 OOM。淘汰触发瞬间可能有轻微延迟抬升(大量 DEL),4.0+ 开启 lazyfree 能把删除异步化。
redis-cli CONFIG SET maxmemory-policy allkeys-lru
redis-cli CONFIG SET lazyfree-lazy-eviction yes持久化抖动:RDB fork 与 AOF 刷盘
RDB 的 BGSAVE 需要 fork 子进程,实例越大 fork 越慢(页表复制),期间主线程会短暂停顿——大实例周期性卡顿时先查 INFO stats 的 latest_fork_usec。AOF 默认 everysec 是折中值;改 always 会把每次写入都 fsync,吞吐骤降。
如果 Redis 只是纯缓存、数据可重建,直接关持久化(save ""、appendonly no)能消掉一整类抖动来源,也是最常见的「免费」优化。
redis-cli INFO stats | grep latest_fork_usec # fork 耗时(微秒)应急与预防清单
线上卡顿应急:① SLOWLOG 定位命令;② 大 key 用 UNLINK(异步删除)代替 DEL;③ 必要时对非关键实例重启。预防:① 把大集合拆小(分片 key);② 全量遍历一律改 SCAN 游标;③ maxmemory 设为物理内存的 70% 以下;④ 监控 used_memory、慢日志条数与主从延迟三个指标。把这套清单贴进值班手册,Redis 故障的 MTTR 能降一半。
redis-cli UNLINK <big-key> # 异步删除,不阻塞主线程