面试的项目环节不是复述简历。简历上那一行"负责订单系统重构"已经写完了,面试官要的是把它拆开:你到底碰过哪一层、遇到什么在拦你、为什么选了这个方案、结果怎么验证的。
讲不清通常不是表达能力问题,而是自己没想清楚约束是什么。约束缺失,任何决策都无法被评价,听起来就像"我们用了 Kafka,因为 Kafka 好"。
1. 面试官在判断的四个信号
| 信号 | 他在听什么 | 听不到就会怀疑 |
|---|---|---|
| 真实性 | 具体到模块名、字段、报错、时间点 | 全程只有"我们团队""大概""后来优化了" |
| 定位能力 | 你能否指出问题出在哪一层 | 只描述现象,说不出根因链路 |
| 取舍意识 | 为什么这么选,放弃了什么 | 只有一个方案,且"没有缺点" |
| 边界认知 | 这套方案在什么条件下会失效 | 把方案说成普适的、无代价的 |
2. 四段结构
① 背景与约束(30 秒)
- 业务在做什么、规模量级、团队与时间约束、技术栈限制
② 你的职责(20 秒)
- 我负责哪几个模块,哪些是我决策的,哪些是别人决策我执行的
③ 关键决策与理由(90 秒,主体)
- 问题 → 可选方案(至少两个)→ 判断依据 → 选了什么 → 代价是什么
④ 结果与验证(30 秒)
- 用什么度量、怎么观测、上线后看到什么、还有什么没解决
四段的顺序不能换。先讲结果("QPS 提升了")会让后面的技术细节失去参照系——听的人不知道这个数字相对于什么基线。
时长控制按岗位级别调整:初/中级讲 2 分钟到一个决策点;高级讲 4–6 分钟、两到三个决策点。主动留出追问接口比讲完更重要:在决策处说一句"这里当时还有个备选是 X,但代价是 Y,所以没选",面试官自然会追这里。
两分钟版(先给骨架,不展开):
"我负责订单创建链路:原来一次下单要串行发 3 个 RPC,
我把它合并成一次批量查询,并加了幂等键防重复。
约束是 3 人团队、不能停机、库存必须强一致。"
被追问后按层展开:
机制(怎么合批)→ 参数(超时、批大小)→ 边界(下游部分失败怎么办)
3. "约束"为什么必须最先说
同一个决策在不同约束下评价完全相反:
| 约束条件 | 合理选择 | 不合理的对照 |
|---|---|---|
| 团队 3 人、半年上线 | 单体 + 模块化,先不拆 | 上微服务,运维成本压垮进度 |
| 日订单 10 万、读多写少 | 主从 + 缓存 | 直接上分库分表,复杂度白付 |
| 强一致的资金流水 | 单库事务、串行化关键段 | 最终一致 + 补偿,对账压力转移给业务 |
| 已有 Hadoop 生态、离线为主 | 复用现有集群 | 另起一套实时链路,双份成本 |
讲述时把约束说成事实而不是借口:"当时只有 3 个人、要给双十一前上线,所以没拆服务"——这是约束;"我们觉得微服务太复杂了"——这是偏好。
4. 量化结果:不编数字,说清度量和量级
面试里最容易失分的一句话是"性能提升了 300%"。没有基线、没有度量方式、没有观测窗口,这句话等于零信息,还会引出"你怎么测的"这种必杀追问。
不合格:优化后接口快了很多,QPS 提升 3 倍。
合格(口径示例,数字为示意):这个接口原来 P99 在 800ms 量级(网关侧统计,采样 1 分钟粒度),
主要耗时在 3 次串行 RPC;改成批量查询后,RPC 次数降到 1 次,
P99 落到 200ms 量级。这个数字是上线后一周的监控读数,
高峰期会有波动,具体取决于下游缓存命中率。
三个要点:
- 单位与口径:P99 还是均值、网关侧还是应用侧、是否含重试。
- 量级而非精确值:"百毫秒量级""下降约一半",比"提升了 287%"更可信。
- 归因边界:改动只影响哪一段,其他因素(流量变化、下游升级)是否同时发生。
如果确实没有度量数据,就直说:"这块没有留下可对比的基线,我只知道变更前后的监控曲线形状变了,具体数字不能确认。" ——承认这一点,可信度反而上升。
5. 技术深度怎么展开:从机制讲到边界
被追问"这个方案具体怎么实现的",正确的展开顺序是三层,而不是把结论换个说法重复:
机制层:它内部怎么工作(数据结构、协议、状态机)
↓
参数层:关键参数是什么、为什么取这个值、调错了会怎样
↓
边界层:什么条件下它会失效、失效时表现是什么、你怎么发现的
举个对照:
| 追问 | 差的回答(停在结论) | 好的回答(进到边界) |
|---|---|---|
| 为什么用 Redis 做分布式锁 | "Redis 性能好" | "SETNX + 过期时间,单实例下够用;主从切换时锁可能丢,所以对强一致场景我改用数据库行锁或 Redisson 的看门狗 + fencing token" |
| 消息为什么不会丢 | "Kafka 很可靠" | "生产端 acks=all,消费端手动提交 offset,业务幂等靠唯一键;重复消费是允许的,丢失不允许" |
| 缓存怎么保持一致 | "用消息队列通知" | "先更新库再删缓存,删除失败进重试队列;接受毫秒级不一致,靠 TTL 兜底" |
深度不是背更多名词,而是知道这东西在哪里会坏。
6. 常见追问的拆解
| 追问 | 真实意图 | 应答骨架 |
|---|---|---|
| 为什么不用 X? | 你有没有比较过 | 说出 X 的两个具体代价(运维/一致性/学习成本),再说你的场景为什么不能接受 |
| 流量涨十倍会怎样? | 你知道瓶颈在哪吗 | 先指瓶颈组件(DB 连接数、单机带宽、锁竞争),再给两级应对(垂直/水平),最后说哪一级先撞墙 |
| 出过什么故障? | 你是否真在一线 | 时间点、现象、定位路径、根因、修复、后续预防,六项齐全 |
| 怎么发现问题的? | 观测能力 | 告警指标 + 日志/链路定位路径,别只说"用户反馈" |
| 这块是你做的吗? | 边界 | 明确说"设计是我,编码是 A,联调是 B",不模糊 |
"出过什么故障"这一问几乎必答,且最能区分真假。准备两个案例:一个是自己的代码 bug,一个是架构层面的问题,各讲一条完整链路。
故障讲述六件套(缺一项就会被追着补,以下为骨架示例):
时间 故障发生的时刻与持续时长(按监控曲线还原,给量级)
现象 下单接口 5xx 上升,支付回调堆积
定位 先看网关错误率 → 应用日志发现连接池耗尽 → 定位到慢查询
根因 新增的列表查询漏了索引,单次扫表把连接吃满
修复 临时扩池 + 回滚该查询,2 小时后补索引上线
预防 慢查询告警阈值下调;上线检查单加"新增查询必须 EXPLAIN"
7. 不会的问题:承认边界 + 给推理路径
硬编的代价是后面每一问都会塌。正确做法是三步:
1. 明确边界:"这块我没做过,我只从文档和别人的分享里了解过。"
2. 给推理:"但如果让我做,我会先确认 A(约束),再看 B(可选项),
倾向选 C,因为在这个场景下 D 的代价更大。"
3. 把决定权交回:"你们实际是怎么处理的?我想知道我的推理哪里偏了。"
这个动作展示的是可迁移的思考,而记忆型问题本来就不是项目环节的重点。
8. 反面示例与改法对照
| 反面 | 问题 | 改法 |
|---|---|---|
| "我们团队把系统重构成微服务" | 主语是团队,个人贡献为零 | "我负责把订单与库存的边界拆开,定义了 6 个接口" |
| "用了 Spring Cloud 全家桶" | 只有技术栈,没有决策 | "选它是因为团队已熟悉,代价是注册中心成为单点,我们加了本地缓存降级" |
| "性能提升明显" | 无度量 | 给口径 + 量级 + 观测窗口 |
| "没有遇到什么问题" | 不可信 | 讲一个真实的小坑,比讲十个优点有效 |
| 讲了 8 分钟还没到结果 | 没有层次 | 先给 30 秒版本,再按追问展开 |
9. 排错:讲完之后常见的四种反弹
| 现象 | 根因 | 处理 |
|---|---|---|
| 面试官反复问同一个点 | 你的回答停在结论层 | 换机制层重讲,主动给参数与失败场景 |
| 追问越来越细直到你答不上 | 开场把范围铺太大 | 主动收窄:"我只讲订单创建的链路,其他模块我没深入" |
| 对方明显失去兴趣 | 缺约束与取舍,听起来像背书 | 立刻插入"当时还有个备选是…" |
| 被质疑"这不是你做的吧" | 细节密度不够 | 补具体报错、字段名、上线时间、评审结论 |
10. 边界:什么内容不该放进项目讲述
| 不该讲 | 原因 |
|---|---|
| 公司机密、真实用户数据 | 换个量级描述即可,不必给真实数字 |
| 只属于团队流程的事(排期、评审会) | 与个人技术判断无关 |
| 无法验证的效果("用户体验提升") | 无法度量,等于没讲 |
| 纯工具使用("我会用 Jenkins") | 放到技能环节,别占项目时间 |
一句话收口:先给约束,再给职责,决策讲清代价,结果给出口径;深度体现在"它什么时候会坏"。
11. 自测
- 为什么"约束"必须先于"决策"讲?举一个约束改变结论的例子。
- 说"P99 从 800ms 降到 200ms"时,必须额外交代哪三件事?
- 被追问"为什么不用 X",回答里必须包含哪两类信息?
- "出过什么故障"这一问,完整链路包含哪六个要素?
- 遇到完全没做过的技术问题,三步应答是什么?
- 你的项目讲述里,哪一句是"可被追问的接口"?现在能展开到边界层吗?