系统设计面试解题框架

一个面试现场的对比

候选人 A 被问到"设计 Twitter":

A:画了个图,说用 Redis 缓存,用 MySQL 存储,说完了。
面试官:能支撑多少用户?
A:呃...很多?
面试官:Redis 挂了怎么办?
A:...不知道。

候选人 B:

B:先问:DAU 是多少?平均每人关注多少人?每天发多少推文?
面试官:DAU 1亿,平均关注 500 人,平均每天发 5 条。
B:好,那我来分析一下流量...
(5分钟后)
B:我的方案分三个阶段:第一阶段用简单架构,第二阶段加缓存,第三阶段扩展。
面试官:好,你觉得哪里是瓶颈?
B:Feed 读取是最大的挑战,因为...

区别在于:有没有方法论。


二、四步解题法🔴

Step 1: 需求澄清(5分钟)

必问的 5 个问题

问题为什么重要
DAU/MAU 是多少?决定系统规模和架构
峰值 QPS 是多少?决定缓存、限流策略
核心功能是什么?确定 MVP 范围
数据量有多大?决定存储选型
可用性要求?决定容灾策略

问题模板

"我先确认几个问题:
1. 系统的用户规模和增长预期?
2. 核心功能有哪些?(必须有的 vs 可以后加的)
3. 性能指标要求?(延迟、吞吐量)
4. 可用性要求?(SLA 是多少)
5. 有什么特殊约束?(预算、技术栈、团队能力)"

Step 2: 高层设计(10分钟)

画出核心组件

┌─────────────────────────────────────────────┐
│              用户请求                          │
│                   ↓                           │
│         ┌─────────────────┐                   │
│         │   Load Balancer │                   │
│         └────────┬────────┘                   │
│                  ↓                            │
│         ┌─────────────────┐                   │
│         │   API Service    │                   │
│         └────────┬────────┘                   │
│                  ↓                            │
│     ┌────────────┼────────────┐              │
│     ↓            ↓            ↓                │
│ ┌───────┐  ┌───────────┐  ┌───────────┐      │
│ │ Cache │  │  Service  │  │   Queue   │      │
│ └───────┘  └─────┬─────┘  └─────┬─────┘      │
│                  ↓                  ↓          │
│            ┌───────────┐      ┌───────────┐  │
│            │  Database  │      │   Kafka   │  │
│            └───────────┘      └───────────┘  │
└─────────────────────────────────────────────┘

API 设计

// 核心 API
POST   /api/v1/feed          // 创建动态
GET    /api/v1/feed          // 获取 Feed
POST   /api/v1/users/{id}/follow   // 关注用户
DELETE /api/v1/users/{id}/follow   // 取消关注

Step 3: 核心细节设计(15分钟)

选一个核心问题深入

Twitter 面试的核心问题通常是 Feed 系统:
1. 如何存储用户的 Feed?
2. 如何生成 Feed?
3. 如何高效读取 Feed?
4. 如何处理新用户关注?

选一个,深入讲。

深度分析模板

问题:如何生成用户首页 Feed?

方案 A:拉模式(Pull)
- 读取时聚合所有关注用户的动态
- 优点:写入快、数据一致
- 缺点:读取慢、复杂度高
- 适用:粉丝数少、读取量低

方案 B:推模式(Push)
- 发推时推送给所有粉丝
- 优点:读取快
- 缺点:写入量大(大V问题)
- 适用:粉丝数多、写入量低

方案 C:混合模式(Hybrid)
- 普通用户推,大V拉
- 阈值:粉丝数 > 10000 用拉模式
- 优点:兼顾读写
- 缺点:复杂度最高

Step 4: 权衡与扩展(5分钟)

讨论 trade-off

面试官:"Redis 挂了怎么办?"

好的回答:
"这里有一个权衡:
- 如果 Redis 不可用,我可以降级到数据库查询
- 但这会导致性能下降 10-100 倍
- 所以我需要限流保护数据库
- 同时需要告警通知运维

或者:
"Redis 挂了意味着 Feed 系统不可用。
我可以做多级降级:
1. L1 本地缓存 → 热点数据
2. L2 Redis → 主缓存
3. L3 MySQL → 最终兜底

每层故障时自动降级到下一层。"

三、高频系统设计题分类🔴

3.1 存储类

题目核心问题关键方案
设计短链系统ID 生成雪花算法 + Base62
设计分布式 ID唯一 ID雪花算法、号段模式
设计排行榜排名计算Redis ZSet

3.2 流处理类

题目核心问题关键方案
设计 Feed 流推拉模式Hybrid 模式
设计秒杀系统库存扣减Redis Lua、MQ
设计消息系统消息路由WebSocket、路由表

3.3 检索类

题目核心问题关键方案
设计搜索框全文检索ES、倒排索引
设计附近的人地理查询Geohash、Redis GEO
设计推荐系统协同过滤矩阵分解

四、容量估算模板🔴

4.1 数据量估算

假设:
- DAU = 1 亿
- 每人每天操作 = 10 次
- 平均数据大小 = 1 KB

计算:
- 日写入量 = 1亿 × 10 × 1KB = 1 TB
- 年存储量 = 1TB × 365 = 365 TB
- 考虑备份 = 365TB × 3 = 1 PB

4.2 QPS 估算

假设:
- DAU = 1 亿
- 日活跃 = 10%
- 日请求 = 1 亿 × 10% × 10 = 1 亿次
- 峰值系数 = 10

计算:
- 平均 QPS = 1亿 / 86400 ≈ 1200
- 峰值 QPS = 1200 × 10 = 12000

五、面试话术模板🟡

5.1 开头

"好的,让我先确认一下需求..."
"在开始设计之前,我想问几个关键问题..."

(确认完需求后)
"根据你说的 DAU 是 X,我估计峰值 QPS 大约是 Y,
核心挑战是 Z..."

5.2 方案陈述

"我的方案分三个阶段:

第一阶段(MVP):用最简单的方式实现核心功能
- 组件:单机房、单机
- 数据:单库

第二阶段(扩展):解决主要瓶颈
- 缓存层
- 读写分离

第三阶段(高级):应对未来增长
- 分库分表
- 多活部署
"

5.3 被追问时

面试官:"这个方案有什么问题?"

好的回答:
"这个方案的问题在于 X 和 Y。
具体来说:
- X 会在 Z 场景下成为瓶颈
- Y 可能会导致一致性问题

我的解决方案是...或者接受这个限制,因为..."

5.4 权衡讨论

面试官:"你选 A 方案而不是 B 方案,为什么?"

好的回答:
"A 和 B 各有权衡:
- A 的优势是...劣势是...
- B 的优势是...劣势是...

我选择 A 是因为在我的场景下,...更重要,而...不是主要矛盾。
如果...发生了变化,我会切换到 B 方案。"

六、常见陷阱🟡

陷阱表现解决
不澄清需求直接开始画图先问 DAU、QPS、功能范围
过度设计一上来就微服务先 MVP,再逐步扩展
不讨论失败只讲成功场景主动讨论故障处理
不量化"应该够用"给出具体数字
不承认局限"我的方案完美"承认权衡,说明选择原因

【面试官心理】 系统设计面试的核心是权衡能力。没有完美的方案,只有适合的方案。面试官想看的是:你能不能识别关键权衡、做出合理决策、并说清楚原因。


七、面试总结

级别期望表现
P5能澄清需求,画出基本架构
P6能深入一个核心问题,给出多种方案对比
P7能做完整的容量估算,主动讨论权衡