
简历写“高并发”面试被问Redis CPU飙升到底怎么回答如果你的简历上写着“高并发”三个字那 Redis 的 CPU 飙升问题基本上是你绕不开的一关。面试官不是闲得没事干而是因为“高并发”在简历里太容易被夸大了这也是最能在现场暴露出真实水平的话题。我见过不少候选人八股背得滚瓜烂熟一旦被问到“线上 Redis CPU 100% 怎么办”就开始东拼西凑回答里既没有定位思路也没有处理手段听到一半面试官基本就已经没了兴致。这篇文章不是让你死记硬背一个标准答案而是帮你理清楚Redis CPU 飙升到底由什么引起面试官问这个问题时想听到什么以及你自己在线上遇到这个问题时从哪一步开始排查。读完再面试你至少不会卡壳就算真在线上遇到了你也有了一个能直接落地的操作清单。1. 先把CPU飙升的根因框架搭起来回答才有骨架很多人一上来就答“缓存穿透”“大key”但这属于典型的“背题式答题”。如果你连 CPU 是被谁消耗的消耗在哪个环节都不清楚就算把所有答案背出来面试官追问三句也会露馅。1.1 Redis的高性能不等于零成本CPU预算也要省着花Redis 是内存数据库CPU 确实不是它的主要瓶颈但这不代表 CPU 上永远不会出问题。Redis 的核心操作链路是在单线程的事件循环里完成的一次命令的执行从网络读到命令解析再到内存操作最后写回缓冲区每一步都在消耗 CPU 时间片。你可以把 Redis 的单线程模型想象成一条流水线线上的工人只有一个。某个操作特别耗时这条流水线就会堵住后续所有请求都得排队。大家平时说的“Redis 变慢了”绝大多数时候不是内存不够也不是磁盘没落盘而是这条流水线上出现了“卡脖子的工序”。所以一听到 CPU 飙升脑海里就应该自动浮现出这条流水线想想是哪个环节疯狂占用时间片。1.2 把CPU消耗的来源分成六类我面试新人时如果对方能把 CPU 飙升的根因归成几类哪怕不够全面我都会觉得这人是有排查经验的。这里我把自己实际用过的归类列出来大致是这么六类根因类别典型表现举例热 Key 集中请求某个 key 被海量请求打爆一个网红账号的数据被疯狂读取大 Key 操作单个 key 的 value 过大读一次就耗很久一个 key 里存了 2MB 的 JSON 字符串慢命令使用了时间复杂度高的命令KEYS、SMEMBERS、HGETALL、ZRANGE 大范围过期回收风暴大量 key 同时过期后台清理线程压力大缓存 key 设置了相同的过期时间持久化开销RDB 快照或 AOF 重写频繁触发写量很大时频繁 fork 和写盘客户端与序列化开销连接数过多、对象反复序列化每一次读都做 JSON 反序列化注意这六类问题还不是互斥的。真实的线上故障往往是复合型的比如一个大 key 刚好又是热 key访问量一上来CPU 就直奔 100%。面试时如果能说出“这几种问题组合出现”的可能性就已经比大多数候选人高半个段位了。1.3 定位优先级先看命令统计再猜原因很多经验不足的同学喜欢靠猜一上来就说“肯定是缓存穿透”。但正确的排查逻辑不是猜而是用数据定位。Redis 本身已经给了我们很多现成的观测工具关键是你会不会用。线上第一件事是执行redis-cli info commandstats看看哪个命令的调用次数和耗时占比最高。这个命令会列出所有命令的调用次数、总耗时和平均耗时。CPU 飙升时这个输出会非常直观地告诉你到底是谁在消耗 CPU。看命令总耗时占比是最快的定位方式。比如输出里hgetall的耗时占比占了 80%那你根本不用怀疑别的问题几乎一定出在大 hash 结构上。拿到这个数据再去回答“怎么办”思路就顺了。2. 面试应答主框架四步法让回答显得既有逻辑又有经验面试官问“Redis CPU 飙升怎么排查”其实想看的不是你记住了多少命令而是你有没有一套成熟的排障思路。我推荐你在面试时按四步来答这套框架不管面试官怎么追问你都不会乱。2.1 第一步确认现象。先分清是谁的CPU高不要一听到“CPU 飙升”就开跑。线上所谓的“CPU 飙了”至少要先确认是 redis-server 进程本身占了高 CPU还是 redis 所在的那台机器整体 CPU 飙了。这两者的排查方向完全不同。如果是 redis-server 进程占满了 CPU那你需要往命令、key 设计、客户端方向上想如果是机器整体 CPU 占用高但 redis-server 只占了一小部分那问题可能出在同机部署的其他进程上比如 Linux 的日志采集 agent、监控 agent甚至是同一台机器上部署了别的应用。面试时主动说出这一点会显得你“看问题有分层意识”。因为线上真实的告警能看到的多半是整机 CPU 高云平台的监控粒度通常到不了进程级别所以第一步永远是缩小范围。自己加这一步回答立刻显得与众不同。2.2 第二步抓现场数据而不是凭感觉确认了是 redis-server 的 CPU 高之后别急着开搞先抓现场。这一步的核心就是“用数据替代猜测”。常用的操作有三组命令按优先级排序大概是下面这样。用redis-cli info commandstats看命令耗时的占比确认是不是某个命令的调用量爆炸。接着用redis-cli --bigkeys扫描大 key看有没有超大 value。再用SLOWLOG GET 20看慢日志看看哪些命令卡在事件循环里了。如果还想看更细一级的可以用redis-cli monitor直接抓实时的命令流但注意这个命令本身就挺耗性能线上谨慎使用。我一般在抓完上面三组数据还没定位到问题时才会考虑用 monitor而且只会开个几秒抓一把流量就立刻关掉。2.3 第三步把现象归因到某一类根因有了数据接下来就是对号入座。如果你发现某个 key 的读 QPS 极高而且commandstats里那条命令的时间占比也很高那就是热 key 叠加了高复杂度操作。如果你发现bigkeys扫出来一个 500KB 甚至 1MB 以上的大 key而且它被高频读取那 CPU 就是在序列化、拷贝、内存分配上烧的。这里我要特别提一个容易被忽略的点不一定是命令本身慢也可能是数据太大导致普通命令变慢。比如一个简单的GET理论上时间复杂度是 O(1)但如果你这个 key 的 value 有 1MB那 GET 的耗时就包括了网络传输、内存拷贝、JSON 反序列化等一系列开销。线上不少人看到GET命令耗时占比高就以为遇到了慢查询其实真正的问题是 value 太大。2.4 第四步给出可落地的治理方案归因之后面试官想听你讲方案了。这一步不要只给一句“加缓存”或者“限流”而是要有针对性地给。如果原因是热 key方案是多级缓存在 Redis 前面加一层本地缓存或者对热 key 做副本拆分把请求分散到多个 Redis 节点上。如果是大 key方案是拆分把一个大的 hash 拆成多个小 hash或者把大字符串拆成多个片段读取时按需获取。如果是慢命令能禁用的禁用比如KEYS就应当直接禁掉线上全部替换为SCAN不能禁用的就控制范围比如对ZRANGE加 limit。如果是过期回收风暴那就把固定过期时间改成在基础值上增加随机偏移量让 key 的过期时间分散开。如果是持久化开销从 RDB 改成 AOF或调低 rewite 触发的阈值把持久化的频率降下来。最后还有一种常见情况是缓存失效后大量请求穿透到数据库数据库扛不住。解决思路是加“缓存重建锁”和“逻辑过期”把回源动作收敛到少数线程上防止缓存一失效所有请求全部打到数据库数据库崩了又牵连到 Redis 的 CPU 飙高。这个属于串联问题回答出来会非常加分。3. 一个真实的线上CPU飙升排查复盘讲完整的方法框架我带你看一个真实案例。这是我之前负责过的一个业务系统某天下午运维突然报警Redis 所在的机器 CPU 飙到了 100%。业务方反馈接口耗时有明显上升部分请求甚至超时报错。我接手排查的整个过程基本就是四步法的实战版本。3.1 案例背景与现象描述这个业务是一个内容社区类产品Redis 部署是老旧的单节点模式内存 16GBCPU 4 核。正常情况下 Redis 的 CPU 占用都在百分之三四十左右高峰最多到五六十。但那天从 14:30 开始CPU 直接打满top 里看到 redis-server 的进程 CPU 基本维持在 380% 左右4 核机器上已经非常夸张了。因为我之前见过不少类似问题第一反应不是去查具体 key而是先跑info commandstats。你猜输出里排名第一的命令是什么不是GET不是MGET而是GET加上SET的调用量都极高而且GET的平均耗时已经超过了 10 毫秒。平均 10 毫秒对一个 Redis GET 来说太不正常了。理论上纯内存操作应该在微秒级别如果平均耗时到了毫秒级只有两种可能要么网络往返在耗时要么 value 过大在内存拷贝上耗了太久。3.2 一步步抓到根因热Key叠加超大Value第二步我跑了redis-cli --bigkeys果然扫出来一个异常大的 keyvalue 大小接近 2MB是一个账号维度的聚合信息 JSON 字符串。这个 key 就是社区里一个头部账号的缓存存储了它最近一段时间内所有的动态、粉丝列表、互动数据按账号维度做了聚合。每次请求获取这个账号的数据时业务代码都会GET这一整个 2MB 的字符串然后反序列化成 JSON 对象再返回。这个 key 本身访问量就大因为它是头部账号几乎每个进社区的用户都会看他。缓存过期时间设置的是 30 分钟一旦过期所有请求都会同时穿透到数据库做聚合查询再把 2MB 的 JSON 写回去。聚合查询本身要跑十几条 SQL耗时好几秒缓存重建期间 Redis 的 CPU 又被 GET 和 SET 轮番轰炸。这就形成了典型的复合问题热 key 让访问量爆炸大 key 让每次访问都背上沉重的拷贝和序列化开销缓存过期时的重构又加剧了 CPU 和数据库的双重压力。单看任何一个表面现象都容易误判比如只看到 QPS 高可能会去优化客户端连接只看到大 key可能又忽略了它同时是热 key 的事实。3.3 解决方案拆分、本地缓存、逻辑过期三管齐下定位到问题后我做了三个改动。第一把 2MB 的大 JSON 拆成多个小 key按数据类型拆分比如account:base存基础资料account:posts存动态列表account:followers存粉丝数据。每个 key 的 value 控制在了几十 KB 以内单次 GET 的拷贝成本骤降。第二给这个账号的缓存加了一层本地缓存即在业务进程内存里再缓存一份近期的数据本地缓存设置短过期时间比如 10 秒。这样一来只有少数请求会打到 Redis热 key 的访问压力立刻降了下来。第三把原来固定的 30 分钟过期时间改成了逻辑过期。所谓逻辑过期就是 value 里存一个过期时间戳读的时候判断这个时间戳如果过期了就由其中一个请求触发异步重建缓存其他请求直接先返回旧数据。这个方案彻底避免了缓存集中穿透的问题。改完之后Redis 的 CPU 从 380% 降到了 30% 左右接口耗时也从原来的 200 多毫秒降到了 40 毫秒左右。这个案例我讲了无数遍因为它几乎涵盖了 Redis CPU 飙升的所有经典要素。面试时如果能讲出这样一个“背景现象—排查路径—归因分析—解决手段—优化效果”的完整故事那你这个回答基本就是满分级别的。4. 高频追问怎么接单线程、大Key、热Key、击穿面试官不会只让你答一个主问题他一定会往下追问。这里我把几个最常见的问题拆开讲每个都给出了在现场能直接用的回答思路。4.1 为什么Redis单线程还能支撑高并发这个问题几乎是“Redis CPU”的孪生问题问完 CPU 必问单线程。面试官真正想听的不是一句话“因为 I/O 多路复用”而是希望你能把原理拆开。Redis 用单线程模型是因为它的性能瓶颈在网络 I/O 和内存操作上而不是在 CPU 计算上。单线程最大的好处是省掉了线程上下文切换和锁竞争的开销。Redis 本身是基于内存的数据结构服务一套核心操作大多在微秒级完成这时候再来回切线程、抢锁反而是最大的拖累。再加上 I/O 多路复用也就是用 epoll 同时监听成千上万个客户端的连接等待数据到达时的事件循环调度CPU 只需要在事件就绪时处理对应请求。绝大多数请求都充满了网络等待真正需要 CPU 计算的时间很短单线程自然够用了。这里有个加分点Redis 的单线程主要指核心命令执行它并不是完全不能多线程。从 Redis 6.0 开始网络 I/O 的读写处理就已经引入了多线程只是命令执行部分仍然保持单线程。另外像持久化 fork、异步删除、模块加载这些也是额外线程在做的。面试时说出这个细节能证明你不是只背了概念。4.2 大Key发现之后怎么安全删除如果线上发现了一个大 key直接DEL是很有风险的操作。因为DEL一个几百 MB 的 key在单线程下会阻塞 Redis 很久阻塞期间整个 Redis 服务都不可用。回答这个问题的正确姿势是把阻塞风险和渐进式操作讲清楚。Redis 4.0 以后推荐用UNLINK来代替DEL。UNLINK会先把 key 从键空间中移除然后再通过后台线程异步清理真正的内容占用的内存这样主线程就不会被阻塞。对于大集合类型比如大 hash、大 list、大 set除了UNLINK也可以在业务低峰期用HSCANHDEL的方式分批删除一部分元素把一次性的大操作拆散到多次小操作里。回答时顺带提一下经验删除大 key 最怕的就是一边删一边有请求在写这个 key这会儿得先在客户端把对这个 key 的访问切走或限流再做删除。否则你删了半天写进去的数据又让 key 变大删了个寂寞。4.3 热Key的发现和治理手段热 Key 的发现大概有三种方式。一是客户端统计在访问 Redis 的 SDK 层把每次 key 的访问次数做一个本地计数定期上报二是 Redis 4.0 之后可以把自己的淘汰策略设置为allkeys-lfu然后通过OBJECT FREQ key查看某个 key 的访问频率三是像阿里云 Redis 这类云上版本自带热点 key 检测功能。当然自建 Redis 也能用redis-cli monitor抓取一段时间的请求来分析但这个方法对高 QPS 的线上环境不太友好抓久了本身还会影响性能。治理方面热 key 的终极手段是多级缓存。进程本地缓存一发把大量读取截胡在应用层。实在没法加本地缓存的场景就做 key 分片比如一个热 key 拆成key:01、key:02…… 把请求分散到多个 key 上存储多份相同的副本读取时随机取一个副本。4.4 缓存击穿、穿透、雪崩怎么区分这三个概念经常被混为一谈但我发现能把它们讲清楚的人处理 Redis CPU 问题时思路都会更清晰。缓存穿透是指请求的数据在 Redis 和数据库中都不存在每次请求都毫无阻挡地打到数据库。这种情况可以用布隆过滤器在 Redis 之前加一层过滤把不存在的 key 挡掉或者对空结果也做缓存比如缓存一个空值只是过期时间设短一些。缓存击穿是指一个热点 key 在过期的一瞬间大量请求同时穿透到数据库。解决办法就是前面说的逻辑过期 互斥锁让同一个 key 在同一时刻只有一个请求去重建缓存其他请求要么等一会儿要么先返回旧数据。缓存雪崩是指大量 key 在同一段时间内集中过期请求同时穿透到数据库。解决办法特别简单给 key 设置过期时间时手动加一个随机值让过期时间分散开。这仨概念的区别面试时建议用一个时间维度去串穿透是“数据不存在”击穿是“一个热 key 过期”雪崩是“一批 key 同时过期”。5. 简历怎么写“高并发”面试才能不翻车主问题都聊完了最后回到起点——简历上的“高并发”。这个问题其实不只是 Redis 的技术问题而是怎么让你的简历内容经得起面试官的追问。5.1 把“高并发”从形容词变成量化指标我看了太多简历写“负责高并发系统开发”但你问他是多高并发峰值 QPS 多少单机多少集群多少他说不上来。这就是简历翻车的开始。写高并发相关经历一定要把量化指标写清楚。比如“支撑每秒 5000 请求的订单查询接口Redis 集群峰值 QPS 8 万接口 P99 延迟低于 100ms”。这种表述才有信息量面试官一眼就知道你做的东西是真的有流量而不是概念性的高并发。同时写清楚你在这个系统里做了什么比如“设计了多级缓存架构把热 key 响应时间从 200ms 降到 30ms”“通过分析命令耗时慢统计定位并拆分了大 keyRedis CPU 峰值降低 60%”。这些描述里有场景、有手段、有结果面试官追问时你也有故事可讲。5.2 面试前建立自己的排障清单无论你是真遇到过高并发问题还是准备去面试都建议你抽时间建立一份自己的 Redis 排障清单。我自己的清单大概是这样的第一CPU 高时先看info commandstats确认哪个命令消耗占比最大。第二用--bigkeys扫大 key用SLOWLOG看慢日志用CLIENT LIST看连接数。第三根据现象归类是命令问题、数据问题还是流量问题。第四对每一种问题提前准备一套可执行的治理方案。这份清单花不了太多时间但面试前过一遍和你现场临时头脑风暴效果天差地别。我在实际带人的时候发现很多新人把问题想复杂了觉得没有见过真实故障就很难回答。但其实面试官要的不是你见过每个故障而是你有没有一套系统性的判断逻辑。只要你的排查路径清晰工具使用得当方案有取舍依据就已经证明了你具备了解决未知问题的能力。5.3 最后分享一个我自己的小习惯线上出过几次 Redis 问题之后我现在不管什么环境都会把redis-cli info commandstats的指标接进监控系统定期看看命令的耗时占比变化。这个指标比单纯看 CPU 使用率要提前很多命令耗时的异动往往比 CPU 飙高早几分钟出现。技术人员最怕的其实不是故障本身而是故障发生的时候手忙脚乱、没有数据、只能靠猜。只要数据到位Redis CPU 飙升这种问题不吓人。希望下次面试官问到这个问题时你能淡定地说出第一句话“我先确认一下是 redis-server 进程本身 CPU 高还是机器整体高”