redis cpu 100% 是主线程被高耗时或高频操作阻塞的明确提示,需优先用 slowlog get 定位“又慢又高频”命令(如 keys*、hgetall 大 key),结合 --hotkeys(需 lfu 策略)和集群 slot 分布分析热 key,避开 monitor 失效陷阱,严禁直接重启。

Redis CPU 100% 不是“要挂了”的信号,而是主线程被某类操作死死占住的明确提示——它仍在响应,但已无法处理新请求的排队逻辑。直接杀进程或重启会丢数据,也掩盖真因;必须先稳住、再定位、最后拆解。
redis-cli --stat 只能帮你排除流量突增,不能定位具体命令
执行 redis-cli --stat 后如果看到 instantaneous_ops_per_second 从 3k 猛涨到 50k,说明是请求洪峰压垮了单线程模型;但如果数值平稳(比如一直维持在 8k),而 top -p $(pgrep redis-server) 显示 CPU 持续 100%,那基本可断定是某个低频但高耗时的操作卡住了主线程。
- 别信
redis-cli monitor:CPU 已满时它自身输出会卡顿、滞后甚至丢命令,看到的可能是 3 秒前的命令流 -
redis-cli --bigkeys和redis-cli --hotkeys都有前提:前者需 Redis ≥4.0,后者依赖maxmemory-policy开启 LFU(如allkeys-lfu),policy 是noeviction时直接返回空 - 真正藏得深的罪魁,常是结构级操作:比如
ZRANGE bigzset 0 -1 WITHSCORES扫了 50 万成员,它不会被标记为 hot key,但会让主线程 hang 200ms+
slowlog get 10 是第一手证据,但要看调用频次+耗时双维度
执行 redis-cli SLOWLOG GET 10,重点不是找「最慢」那条,而是找「又慢又高频」的组合:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 如果出现一堆
KEYS *,不用犹豫,这就是元凶——它遍历全库,复杂度 O(N),数据量越大越致命 - 如果看到大量
HGETALL user:123456:profile,且该 key 是个几 MB 的 hash,说明客户端在反复拉全量结构,应改为按需HGET - 如果
UNLINK出现在 slowlog 里且耗时长,说明正在异步删大 key,但主线程仍需做元数据清理;此时DEL更快但会阻塞,UNLINK更安全但更吃 CPU
热 Key 导致的 CPU 倾斜,在集群中表现完全不同
单机 Redis CPU 100% 多是命令或数据问题;集群中某节点 CPU 长期 95%+,其他节点才 20%,八成是热 Key 打在了那个分片上——不是配置问题,而是哈希分布失衡。
- 先确认该节点是主节点:
redis-cli -c -h [ip] -p [port] INFO replication | grep role,确保不是从节点同步拖累 - 对比各节点的
keyspace_hits / keyspace_misses比值,热 Key 节点命中率通常 >99.5%,但used_cpu_user持续飙升 - 别指望删 Key 解决:强行
DEL或加短过期会引发缓存穿透 + 雪崩式重载;业务逻辑没改,新生成的 Key 还是落到同一个 slot(比如hot_user:{id}哈希后始终进 slot 5432) - 真正有效的降级动作是:在客户端层对热 Key 做本地缓存(如 Caffeine)、加读写分离代理(如 Twemproxy 分流)、或拆 Key(如把
user:123456拆成user:123456:base+user:123456:ext)
Pub/Sub 客户端死循环才是最隐蔽的 CPU 杀手
Redis 服务端的 SUBSCRIBE 本身不耗 CPU,但客户端一旦写错逻辑,就会让自己的进程空转,同时不断重连、重复订阅,最终把 Redis 连接数和自身 CPU 全打满。
- 典型错误模式:
while True:包裹pubsub.get_message()却没设timeout,连接断开后底层变成忙等 - Java 中复用
JedisPubSub实例于多线程,或onMessage里做了 DB 查询,阻塞事件线程导致消息积压、重试激增 - 快速验证法:在应用服务器上
strace -p [pid] -e trace=epoll_wait,recvfrom,如果看到大量epoll_wait返回 0 或频繁recvfrom失败,就是客户端在空轮询 - 硬性约束必须遵守:每个 Pub/Sub 连接独占一个 TCP 连接;必须监听
error/reconnect事件并在回调里显式unsubscribe()+ 指数退避重连(初始 1s,上限 30s)
真正难处理的从来不是命令本身,而是那些「看起来合理却在特定规模下失控」的组合:比如一个每秒只被调用 10 次的 SMEMBERS,在 value 达到 20 万成员时,每次就吃掉 150ms CPU;或者一个本该只在初始化时运行的 KEYS user:*,被误塞进了定时任务里每分钟跑一次。这类问题不会出现在压测报告里,只会在真实流量高峰中突然浮出水面。










