跳转至

01. 企业场景题:项目追问与八股延伸(综合实战版)

面试里最难的不是八股本身,而是面试官从你的项目或者一道八股延伸出来的场景题。

这类题没有标准答案,但有标准的回答结构:

  1. 拆问题 — 这个场景本质在考什么?
  2. 分层答 — 从系统全局到局部细节,逐层展开
  3. 串知识 — 把涉及的知识点串起来,体现你的知识网络
  4. 提风险 — 主动补边界情况、异常路径和工程代价

下面按"系统设计类 → 性能优化类 → 故障排查类 → 数据一致性类"组织。


先把这一章的知识骨架搭起来

企业场景题的关键,不在于背标准答案,而在于形成一种稳定的拆题方法。因为这类题通常都是“项目 + 八股 + 系统设计 + 排障”混在一起,考的是 你如何在信息不完整的情况下做分析和决策

因此这章建议你始终按“明确目标 → 找瓶颈或风险点 → 给分层方案 → 说明验证手段 → 讲清副作用和回滚”来应对。只要结构稳,场景再变,你也不至于被问乱。

进入场景题之前,先把答题框架固定下来

场景题最大的坑不是不会某个知识点,而是临场被问题带着跑。更稳的办法,是先把自己的答题骨架固定住:目标是什么、系统瓶颈或风险点在哪、有哪些分层方案、用什么指标验证、出了问题怎么回滚。

只要这套骨架稳定,你面对系统设计、性能优化、故障排查、一致性场景时,叙事都会比纯凭感觉更稳。


一、系统设计类场景题

场景 1:设计一个短链接服务

题目: 如何设计一个短链接生成和跳转服务?

回答思路:

1. 核心功能拆解:

  • 长链接 → 短链接的映射生成
  • 短链接 → 长链接的快速查询和 302 跳转
  • 短链接的唯一性保证
  • 过期和清理

2. 关键设计决策:

决策点 方案 理由
ID 生成 自增 ID + Base62 编码 或 哈希截取 Base62 编码短、可读;哈希截取要处理冲突
存储 MySQL(持久化)+ Redis(热点缓存) 写入量不大用 MySQL,读远大于写所以加缓存
跳转方式 301 永久重定向 或 302 临时重定向 302 更灵活(方便统计点击量),301 对 SEO 更友好
过期机制 记录创建时间 + TTL,定时清理 避免无限膨胀

3. 串联知识点:

  • 哈希与冲突:如果用哈希方案,怎么处理冲突?→ 数据结构与算法
  • 数据库索引:短链接字段需要唯一索引 → MySQL 索引
  • 缓存策略:热点短链接走 Redis,缓存穿透怎么防?→ Redis 高可用
  • HTTP 重定向:301 vs 302 的区别 → HTTP 详解

4. 主动补充:

  • 高并发下 ID 生成怎么保证唯一?分布式 ID 方案(Snowflake 等)
  • 防止恶意刷短链接:限流、黑名单
  • 统计需求:点击量、地域分布、时间分布

场景 2:设计一个消息推送系统

题目: 如果让你设计一个支持千万级用户的消息推送系统,你怎么做?

回答思路:

1. 核心模块:

  • 连接管理层:维护客户端和服务端的长连接(WebSocket / 自定义协议)
  • 路由层:知道用户当前连接在哪台机器上
  • 消息分发层:把消息投递到正确的连接
  • 离线存储:用户不在线时消息暂存
  • 补偿机制:消息发送失败的重试和确认

2. 关键难点:

难点 解决思路
连接管理 每台机器维护 N 个连接,用户上下线时更新路由表
路由发现 Redis / etcd 存储 user_id → server_id 映射
消息可靠性 ACK 确认 + 重试 + 消息 ID 去重
离线消息 写入消息队列或数据库,用户上线时拉取
推送顺序 单用户维度有序(用消息序列号),跨用户不保证全局序

3. 串联知识点:


场景 3:设计一个分布式定时调度系统

回答思路:

组件 职责
调度器 扫描到期任务,分发执行
执行器 实际运行任务逻辑
锁服务 保证同一时刻只有一个实例执行某个任务(Redis 分布式锁 / 数据库行锁)
日志与监控 记录执行结果、耗时、失败原因

串联知识点:

  • 分布式锁:Redis SETNX + 过期时间 → Redis 高可用
  • 幂等性:任务重复执行了怎么办?→ 系统设计
  • 线程池:执行器内部怎么管理并发?→ C++ 并发

二、性能优化类场景题

场景 4:接口 RT 从 50ms 涨到 500ms,怎么排查?

回答结构(从全局到局部):

  1. 先看监控大盘 — 个别接口还是全局?突发还是逐渐?有没有发布变更?
  2. 检查下游依赖 — 数据库慢查询?Redis 延迟?下游 RPC 超时?
  3. 检查应用层 — 线程池积压?内存分配异常?锁竞争?(火焰图 / perf
  4. 检查基础设施 — 网络抖动?CPU/内存/磁盘 IO 打满?容器资源限制?

串联知识点:


场景 5:数据库查询特别慢,怎么优化?

  1. 定位EXPLAIN 看执行计划:type 是 ALL?扫描行数远大于结果集?
  2. 索引层面 — 缺索引?索引失效?(函数操作列、隐式类型转换、OR、LIKE '%xxx')联合索引最左前缀?
  3. SQL 层面 — 减少 JOIN 表数?覆盖索引避免回表?深度 OFFSET 改游标分页?
  4. 架构层面 — 读写分离、缓存热点数据、大表水平拆分

串联知识点:


场景 6:QPS 突然翻倍,系统扛不住了

  1. 止血 — 限流(令牌桶/滑动窗口)、降级(非核心功能返回默认值)、熔断(下游不可用时快速失败)
  2. 定位 — 正常增长还是异常流量(爬虫、攻击)?哪个接口 QPS 最高?
  3. 扩容 — 水平扩容、缓存预热、异步化能异步的操作

三、故障排查类场景题

场景 7:线上 CPU 飙到 100%

  1. top 找 CPU 最高的进程
  2. top -Hp <pid> 找 CPU 最高的线程
  3. perf top / 火焰图 定位热点函数
  4. 常见原因: 死循环、自旋锁竞争、频繁内存分配释放、正则回溯、CPU 密集计算

串联知识点:


场景 8:内存持续增长,疑似泄漏

  1. top / ps 确认 RSS 持续增长不回落
  2. 工具: Valgrind(精确但慢)、AddressSanitizer(推荐 C++)、pmap / /proc/<pid>/smaps
  3. 常见原因: new 没 delete、容器只增不删、缓存没淘汰、shared_ptr 循环引用、文件句柄没关

串联知识点:


四、数据一致性类场景题

场景 9:缓存和数据库数据不一致

策略 做法 问题
Cache Aside 读:先缓存 miss 查 DB 再写缓存;写:先更新 DB 再删缓存 并发下有短暂不一致窗口
Write Through 写入时同时更新缓存和 DB 写延迟增加
Write Behind 写入缓存后异步刷 DB 数据可能丢失

为什么"先删缓存再更新 DB"不好? 并发场景下另一个读请求可能在删缓存后、更新 DB 前读到旧数据写回缓存。

工程做法: Cache Aside + 合理 TTL 是最常见折中;高一致性场景用延迟双删或订阅 binlog。


场景 10:分布式事务怎么保证一致性?

方案 原理 适用场景
2PC 协调者+参与者,先 Prepare 再 Commit 强一致性,性能差
TCC Try-Confirm-Cancel,业务层实现 灵活但开发成本高
Saga 每步有补偿操作,失败逆序补偿 长事务,最终一致
消息事务 本地事务+消息队列 最常见的互联网方案

如何回答场景题的通用方法论

  1. 先确认问题边界 — "这个系统的 QPS 大概是多少级别?""需要强一致还是最终一致?"
  2. 从高到低分层讲 — 架构 → 核心模块 → 关键细节
  3. 主动提 Trade-off — "这个方案的优点是 XXX,代价是 XXX"
  4. 串联已有知识 — 让面试官看到你的知识不是孤立的
  5. 不要装 — 不确定的就说"这一块我了解有限,但我的理解是 XXX"

关联章节