08-01-B-高并发方法论面试与生产事故实战
️关键词:高并发面试题 · 缓存 · 异步 · 池化 · 预计算 · 分片 · QPS 演进 · 容量规划 · 压测 · 缓存雪崩
📌导读:这是《33-A-高并发方法论详解》的配套 B 篇。A 篇讲"五大手段、QPS 演进路线、容量规划、压测",本篇讲"面试官怎么考、生产上怎么炸、炸了怎么救"。高并发面试是"架构师试金石"——考官不只想听你背五大手段,更想听你讲"按什么顺序用、QPS 10 万怎么设计、容量怎么算",生产事故则集中在"缓存雪崩全穿透、异步丢消息、连接池耗尽、压测没全链路上线翻车"。高频题按知识依赖链一问一答连贯展开(每题: 30 秒电梯版 → 深挖版 → 追问链),事故按场景 → 根因 → 预防 → 解决 → 一句话教训五段式复盘。原理细节标注"见 A 篇 x.x 节"。
📑 目录
- 08-01-B-高并发方法论面试与生产事故实战
- 一、高频面试题精讲(连贯问答链)
- 链条①:五大手段四连问
- Q1:高并发怎么扛?五大手段是什么?
- Q2:缓存怎么扛高并发?有什么坑?
- Q3:异步怎么削峰?有什么代价?
- Q4:分片什么时候用?为什么是最后手段?
- 链条②:QPS 演进与容量三连问
- Q5:QPS 从 1 千到 100 万怎么演进?
- Q6:容量怎么规划?机器数怎么算?
- Q7:QPS 10 万的系统怎么设计?
- 链条③:压测与落地三连问
- Q8:压测怎么做?全链路压测是什么?
- Q9:压测达标了,上线就没事了吗?
- Q10:高并发落地最大的坑是什么?
- 二、生产事故案例集(五段式复盘)
- 事故一:缓存雪崩,大量 key 同时过期,DB 被打爆
- 事故二:异步加积分丢消息,用户积分少了
- 事故三:下游 RT 变长,连接池耗尽,请求排队超时
- 事故四:单服务压测达标,上线全链路翻车
- 三、事故速查表
- 四、面试答题万能框架
- 五、与 A 篇的知识点映射
一、高频面试题精讲(连贯问答链)
链条①:五大手段四连问
Q1:高并发怎么扛?五大手段是什么?
** 30 秒电梯版**
五大手段(见 A 篇第二章):
- 缓存:热点数据放内存,挡掉 90% 读流量——解决读瓶颈;
- 异步:非核心操作放 MQ,主链路只干核心事——解决写峰值/RT 长;
- 池化:连接池/线程池/对象池复用资源——解决资源创建开销;
- 预计算:结果提前算好——解决计算瓶颈;
- 分片:数据/流量水平拆分——解决单机容量上限。
一句话总结:缓存挡读→异步削峰→池化复用→预计算提前算→分片水平拆——成本递增,按瓶颈顺序使用,分片是最后手段。
** 深挖版**
| 要点 | 说明 |
|---|---|
| 使用顺序 | 缓存最先(成本低收益高),分片最后(成本高)——按瓶颈顺序,不是全上 |
| Amdahl 定律 | 优化瓶颈才有效——先找瓶颈再选手段 |
| 组合使用 | 缓存+异步+池化组合——不是单选 |
** 追问链**:缓存怎么用?→ Q2
Q2:缓存怎么扛高并发?有什么坑?
** 30 秒电梯版**
缓存的作用:热点数据放 Redis/本地缓存——读请求先查缓存,命中不查 DB——挡掉 90% 读流量,DB 读 QPS 从 1 万降到 1 千。
三大坑:
- 缓存穿透:查不存在的数据,缓存和 DB 都没有——布隆过滤器拦截;
- 缓存击穿:热点 key 过期瞬间大量请求打到 DB——互斥锁/逻辑过期;
- 缓存雪崩:大量 key 同时过期——过期时间打散+多级缓存。
一句话总结:缓存挡读流量,但有一致性+穿透/击穿/雪崩三大坑——布隆过滤器/互斥锁/过期打散是标配。
** 深挖版**
| 要点 | 说明 |
|---|---|
| 缓存一致性 | 延迟双删/订阅 binlog 更新缓存——详见 Redis 篇 |
| 多级缓存 | 本地缓存(Caffeine)+Redis——Redis 挂了本地缓存兜底 |
| 热点 key | 热点探测+本地缓存——超级热点 key 单独处理 |
** 追问链**:异步怎么用?→ Q3
Q3:异步怎么削峰?有什么代价?
** 30 秒电梯版**
异步的作用:非核心操作(发短信/加积分/推物流)放 MQ——主链路只干核心事(下单/扣库存)——RT 从 500ms 降到 50ms,峰值削平,下游按能力消费。
代价:
- 最终一致:异步操作不是实时完成——用户感知延迟;
- 消息不丢不重:要三端确认+幂等——复杂度上升;
- 排查变难:异步链路要链路追踪——可观测性要求高。
一句话总结:异步削峰换 RT 和峰值,代价是最终一致+消息可靠性+排查复杂度——核心操作同步,非核心异步。
** 深挖版**
| 要点 | 说明 |
|---|---|
| 什么操作异步 | 非核心+可延迟+可重试——发短信/加积分/推物流 |
| 什么操作同步 | 核心+不可延迟——下单/扣库存/扣款 |
| 削峰填谷 | MQ 把瞬时高峰削平,下游按能力消费——高峰不压垮下游 |
** 追问链**:分片什么时候用?→ Q4
Q4:分片什么时候用?为什么是最后手段?
** 30 秒电梯版**
分片解决什么:单机容量上限——缓存+异步+池化+预计算都用完还扛不住,数据/流量水平拆分到多节点(分库分表/CDN/多机房)。
为什么是最后手段:
- 成本高:分库分表引入跨分片查询/扩容迁移/分布式事务——复杂度陡增;
- 不可逆:分片后合不回来——分片键选错代价大;
- 前四者能解决大部分:缓存挡读+异步削峰能扛大部分场景——分片是"前四者用完还扛不住"才用。
一句话总结:分片解决单机上限,但成本高+不可逆——前四者(缓存/异步/池化/预计算)用完还扛不住才分片,分片是最后手段。
** 深挖版**
| 要点 | 说明 |
|---|---|
| 分片键选择 | 查询带得上/分得匀/改不了——选错=白拆(14-A 篇) |
| 分片 vs 多活 | 分片是数据层拆分,多活是地理级拆分——分片后再多活 |
| 何时不分片 | 单表 <5000 万+前四者够用——别过早分片 |
链条②:QPS 演进与容量三连问
Q5:QPS 从 1 千到 100 万怎么演进?
** 30 秒电梯版**
演进五层(见 A 篇第三章):
| 层 | QPS | 架构 | 关键手段 |
|---|---|---|---|
| 1 | 1 千 | 单体+单库 | SQL 索引+连接池 |
| 2 | 1 万 | 单体+缓存+MQ | Redis 缓存+MQ 异步+读写分离 |
| 3 | 10 万 | 微服务 | 服务拆分+治理+应用水平扩展 |
| 4 | 50 万 | 微服务+分片 | 分库分表+缓存集群+MQ 集群 |
| 5 | 100 万+ | 多活 | 多机房/异地多活+流量调度 |
一句话总结:1 千靠优化,1 万靠缓存异步,10 万靠服务化,50 万靠分片,100 万靠多活——每层解决上一层的瓶颈。
** 深挖版**
| 要点 | 说明 |
|---|---|
| 演进不是跳级 | 按瓶颈逐层演进——别一上来就分片 |
| 每层的瓶颈 | 1 千瓶颈在 SQL,1 万瓶颈在读,10 万瓶颈在单机应用,50 万瓶颈在单机数据 |
| 多活的代价 | 数据同步+流量调度+一致性——成本最高,100 万+才用 |
** 追问链**:容量怎么规划?→ Q6
Q6:容量怎么规划?机器数怎么算?
** 30 秒电梯版**
容量规划四步(见 A 篇第四章):① 定目标(目标 QPS/RT/可用性)→ ② 测单机(压测单机 QPS/RT)→ ③ 算资源(机器数/连接数/缓存/带宽)→ ④ 留冗余(冗余系数 1.5~2)。
核心公式:
机器数 = 目标QPS / 单机QPS × 冗余系数 连接数 = QPS × RT(s) × 冗余系数 缓存容量 = 热点数据量 × 单条大小 × 冗余 带宽 = QPS × 单请求大小一句话总结:定目标→测单机→算资源→留冗余——机器数=目标 QPS/单机 QPS×冗余系数,容量规划是反推不是拍脑袋。
** 深挖版**
| 要点 | 说明 |
|---|---|
| 冗余系数 | 1.5~2——应对流量突增/节点故障 |
| 单机 QPS 怎么测 | 压测单机到瓶颈——P99 达标时的 QPS |
| 连接数陷阱 | RT 变长连接数要扩——连接数=QPS×RT,RT 翻倍连接数翻倍 |
** 追问链**:压测怎么做?→ Q8
Q7:QPS 10 万的系统怎么设计?
** 30 秒电梯版**
QPS 10 万 = 第 3 层(微服务):
- 缓存:Redis 集群挡读——读 QPS 几十万;
- 异步:非核心操作 MQ 异步——主链路 RT <100ms;
- 服务化:微服务拆分+水平扩展——应用层 50+ 实例;
- 治理:限流/熔断/降级/隔离——防雪崩;
- 数据层:读写分离+主从——DB 写 QPS 几千够用。
一句话总结:QPS 10 万靠微服务+缓存+异步+治理——应用层水平扩展,数据层读写分离,还没到分片。
** 深挖版**
| 要点 | 说明 |
|---|---|
| 机器数估算 | 10 万 QPS/单机 2000 QPS×1.5 = 75 台应用机器 |
| 瓶颈在哪 | 10 万 QPS 瓶颈通常在 DB 写/缓存热点——读写分离+缓存集群 |
| 要不要分片 | 单表 <5000 万+读写分离够用——10 万 QPS 通常不用分片 |
链条③:压测与落地三连问
Q8:压测怎么做?全链路压测是什么?
** 30 秒电梯版**
压测五步(见 A 篇第五章):① 定目标(目标 QPS/RT/错误率)→ ② 造数据(模拟真实分布)→ ③ 压测执行(JMeter/Gatling/wrk,逐步加压)→ ④ 找瓶颈(CPU/内存/IO/连接/带宽)→ ⑤ 优化+复测。
全链路压测:模拟真实流量压测整条调用链——单服务压测达标≠整条链达标,影子库/影子表隔离压测数据,不污染生产。
一句话总结:压测五步:定目标→造数据→压测→找瓶颈→优化复测——看 P99 不看平均,全链路压测验证整条链,影子数据不污染生产。
** 深挖版**
| 要点 | 说明 |
|---|---|
| 压测指标 | QPS/RT(P99)/错误率/资源——P99 达标才算达标 |
| 影子数据 | 压测数据打标,影子库/影子表存储——不污染生产数据 |
| 压测环境 | 尽量和生产同配置——环境差异导致压测失真 |
** 追问链**:压测达标上线就没事了吗?→ Q9
Q9:压测达标了,上线就没事了吗?
** 30 秒电梯版**
不一定——压测和生产的差异:
- 流量分布差异:压测流量均匀,生产有热点/突刺——热点 key/突发流量压测没覆盖;
- 数据差异:压测数据干净,生产有脏数据/历史数据——数据倾斜/大表;
- 依赖差异:压测下游 mock/稳定,生产下游会慢/会挂——下游故障没压到;
- 时间差异:压测短时间,生产长时间运行——内存泄漏/连接泄漏长时间才暴露。
一句话总结:压测达标≠上线没事——流量分布/数据/依赖/时间四个差异,压测覆盖不到的靠监控+灰度+治理兜底。
** 深挖版**
| 要点 | 说明 |
|---|---|
| 灰度发布 | 压测+灰度双保险——小流量验证生产真实表现 |
| 监控兜底 | 上线后监控 QPS/RT/错误率/资源——异常早发现 |
| 混沌工程 | 主动注入故障(下游慢/节点挂)——验证治理有效性 |
** 追问链**:高并发落地最大的坑是什么?→ Q10
Q10:高并发落地最大的坑是什么?
** 30 秒电梯版**
四大高频坑(详见第二章事故集):
- 缓存雪崩:大量 key 同时过期,全穿透到 DB——DB 被打爆;
- 异步丢消息:MQ 没三端确认,异步操作丢失——数据不一致;
- 连接池耗尽:下游 RT 变长,连接池吞吐暴跌——请求排队超时;
- 压测没全链路:单服务压测达标,上线整条链翻车。
一句话总结:缓存雪崩/异步丢消息/连接池耗尽/压测没全链路——高并发四大坑,每个都是"想当然"的代价。
** 深挖版**
| 要点 | 说明 |
|---|---|
| 缓存雪崩预防 | 过期时间打散+多级缓存+限流兜底 |
| 异步可靠性 | 三端确认+幂等+对账——25-A 篇 |
| 连接池估算 | 连接数=QPS×RT×冗余——RT 变长要扩池 |
二、生产事故案例集(五段式复盘)
事故一:缓存雪崩,大量 key 同时过期,DB 被打爆
** 事故场景**
商品缓存统一设置 1 小时过期,某整点大量 key 同时过期——缓存命中率从 95% 暴跌到 10%,读请求全穿透到 DB,DB CPU 100%,商品查询全部超时,首页打不开。
** 根因分析**
缓存雪崩(Q2):大量 key 同时过期(统一 1 小时过期,同一时间设置)——过期瞬间缓存命中率暴跌,读请求全穿透到 DB。DB 读 QPS 从 1 千(缓存挡 90%)暴涨到 1 万,DB 扛不住。
️ 预防方案
- 过期时间打散:过期时间加随机偏移(如 1 小时±10 分钟)——避免同时过期;
- 多级缓存:本地缓存(Caffeine)+Redis——Redis 过期时本地缓存兜底;
- 限流兜底:DB 限流——缓存穿透时保护 DB;
- 热点 key 不过期:超级热点 key 逻辑过期+异步更新——永不真正过期;
- 缓存监控:命中率监控——命中率暴跌告警。
** 事故解决**
- 止血:DB 限流+紧急预热缓存,命中率恢复;
- 根治:过期时间打散;多级缓存;DB 限流;热点 key 逻辑过期;命中率监控;
- 验证:模拟整点过期,命中率不暴跌,DB 正常。
** 一句话教训**
缓存统一过期时间 = 整点同时过期 = 雪崩全穿透——过期时间打散+多级缓存+限流兜底;缓存命中率是生命线,暴跌即告警。
事故二:异步加积分丢消息,用户积分少了
** 事故场景**
订单支付成功后异步加积分(MQ),某次 MQ Broker 宕机重启——Producer 发送时 Broker 不可用,消息发送失败但没重试/没落库,1000 笔订单的加积分消息丢失,用户积分少了,客诉。
** 根因分析**
异步丢消息(Q3):MQ 发送失败(Broker 宕机)但没三端确认兜底——Producer 没重试、没落库补偿,消息直接丢。异步操作的可靠性靠"三端确认+重试+对账",缺了发送端兜底就丢消息。
️ 预防方案
- 发送端兜底:发送失败重试+落库补偿(本地消息表)——发送失败不丢;
- 事务消息:RocketMQ 事务消息——本地事务+消息发送一致;
- 存储端可靠:Broker 同步刷盘+主从——Broker 宕机不丢;
- 消费端幂等:消费幂等+重试——消费不丢不重;
- 对账兜底:订单 vs 积分对账——丢了靠对账补。
** 事故解决**
- 止血:从订单流水找回 1000 笔,手动补加积分;
- 根治:加积分改事务消息(本地事务+消息一致);发送失败落库补偿;订单-积分对账上线;
- 验证:模拟 Broker 宕机,事务消息+补偿兜底,积分零丢失。
** 一句话教训**
异步发送没兜底 = Broker 宕机丢消息——异步可靠性靠三端确认+重试+对账;核心异步操作用事务消息,发送失败落库补偿。
事故三:下游 RT 变长,连接池耗尽,请求排队超时
** 事故场景**
用户服务调积分服务,积分服务某次 RT 从 10ms 涨到 2s(慢查询)。用户服务的 RPC 连接池(100 连接)——每个连接占用 2s,连接池吞吐=100/2s=50 QPS,远低于用户服务 QPS 500,连接池耗尽,新请求排队等待,全部超时,用户服务不可用。
** 根因分析**
连接池耗尽(Q6 深挖/29-B 事故三):连接池吞吐=连接数/RT——下游 RT 从 10ms 涨到 2s,连接池吞吐从 10000 QPS 暴跌到 50 QPS。连接池大小按正常 RT 估算,RT 变长后连接池不够用,请求排队超时。
️ 预防方案
- 连接池按 QPS×RT×冗余估算:RT 变长要扩池——动态估算;
- 超时配置:RPC 超时 < 连接等待超时——拿不到连接快速失败;
- 熔断降级:下游慢触发熔断——不占连接,走降级;
- 连接池监控:活跃连接数/等待队列打点——接近耗尽告警;
- 下游慢查询治理:积分服务慢查询优化——RT 恢复,连接池吞吐恢复。
** 事故解决**
- 止血:连接池扩到 500+积分服务慢查询优化;
- 根治:连接池动态估算;RPC 超时+熔断配置;连接池监控;
- 验证:压测 500 QPS+下游 RT 2s,连接池 500 支撑,无排队。
** 一句话教训**
连接池吞吐=连接数/RT——下游 RT 变长,连接池吞吐暴跌;连接池按 QPS×RT 估算,下游慢要扩池+熔断。
事故四:单服务压测达标,上线全链路翻车
** 事故场景**
订单服务重构,单服务压测达标(单机 3000 QPS,P99 50ms),上线后整条调用链(网关→订单→用户→积分→DB)P99 从 50ms 涨到 800ms,超时率 5%。排查发现:单服务压测时下游是 mock/稳定的,生产下游有慢调用+连接池竞争+缓存穿透,整条链叠加后不达标。
** 根因分析**
压测没全链路(Q8/Q9):单服务压测下游 mock/稳定,没压到真实的下游慢调用/连接池竞争/缓存穿透——单服务达标≠整条链达标。生产整条链的 RT 是各环节叠加+竞争,单服务压测覆盖不到。
️ 预防方案
- 全链路压测:压测整条调用链,不 mock 下游——真实依赖真实压;
- 影子数据:压测数据打标,影子库/影子表——不污染生产;
- 灰度发布:小流量验证生产真实表现——压测+灰度双保险;
- 链路 RT 监控:整条链 P99 监控——上线后异常早发现;
- 压测环境对齐:压测环境和生产同配置+同数据量级——环境差异导致失真。
** 事故解决**
- 止血:灰度回滚旧版本;
- 根治:全链路压测流程上线(影子数据);灰度发布规范;链路 RT 监控;
- 验证:全链路压测达标+灰度验证,上线 P99 稳定 100ms。
** 一句话教训**
单服务压测达标≠整条链达标——下游慢调用/连接池竞争/缓存穿透单服务压不到;全链路压测+灰度发布双保险,压测环境对齐生产。
三、事故速查表
| 现象 | 可能根因 | 快速定位 | 根治方案 |
|---|---|---|---|
| 缓存命中率暴跌 DB 爆 | 缓存雪崩(同时过期) | 缓存命中率;过期时间分布 | 过期打散;多级缓存;限流 |
| 异步操作丢失 | 发送没兜底 | MQ 发送日志;对账差异 | 事务消息;落库补偿;对账 |
| 请求排队超时 | 连接池耗尽 | 连接池活跃数;下游 RT | 扩池;超时;熔断 |
| 上线 RT 暴涨 | 压测没全链路 | 链路 RT 对比 | 全链路压测;灰度 |
| 读 QPS 扛不住 | 没缓存/缓存穿透 | 缓存命中率;DB 读 QPS | 加缓存;布隆过滤器 |
| 主链路 RT 长 | 同步调用多 | 链路追踪各环节 RT | 非核心异步化 |
| 单机扛不住 | 没水平扩展 | 单机 CPU/连接 | 水平扩展;分片 |
四、面试答题万能框架
加分技巧:
- 谈五大手段主动讲"成本递增按瓶颈顺序用,分片是最后手段——前四者能解决大部分"——架构师的成本意识;
- 谈演进主动带"1 千靠优化,1 万靠缓存异步,10 万靠服务化,50 万靠分片,100 万靠多活——每层解决上层瓶颈"——演进思维;
- 谈容量主动说"机器数=目标 QPS/单机 QPS×冗余系数,连接数=QPS×RT×冗余——RT 变长连接数翻倍"——公式级精确;
- 谈压测主动讲"单服务压测达标≠整条链达标,全链路压测+影子数据+灰度双保险"——实战经验;
- 被问"遇到过什么高并发问题",用事故一(缓存雪崩 DB 爆)——"整点同时过期全穿透"的叙事最有画面感。
五、与 A 篇的知识点映射
| 本篇题目/事故 | A 篇《33-A-高并发方法论详解》对应章节 |
|---|---|
| Q1 五大手段 | 二章 |
| Q2 缓存坑 | 2.2① |
| Q3 异步代价 | 2.2② |
| Q4 分片最后手段 | 2.2⑤/2.3 |
| Q5 QPS 演进 | 三章 |
| Q6 容量规划 | 四章 |
| Q7 QPS 10 万设计 | 三章 |
| Q8 压测 | 五章 |
| Q9 压测达标≠上线没事 | 五章延伸 |
| Q10 落地坑 | 全文 |
| 事故一 缓存雪崩 | 2.2① |
| 事故二 异步丢消息 | 2.2② |
| 事故三 连接池耗尽 | 四章 |
| 事故四 压测没全链路 | 五章 |
📌结语:高并发面试题的尽头是"递进意识"——五大手段成本递增按瓶颈顺序用,QPS 演进每层解决上层瓶颈,不是一上来就分片/多活;生产事故的尽头是"兜底意识"——缓存要防雪崩、异步要防丢消息、连接池要防耗尽、压测要全链路,每个"想当然的可用"都是一次事故的伏笔。
📌配套阅读:
A 篇:《08-01-A-高并发方法论详解.md》下一篇:《08-02-A-秒杀系统设计详解.md》
如果这篇文章对你有帮助,欢迎点赞、收藏、关注!