系统设计入门:如何准备大厂面试中最难的环节
系统设计面试是大厂后端/架构岗位的核心考察环节,也是最能拉开候选人差距的部分。本文从零讲解系统设计面试的框架:如何在 45 分钟内完成一个系统的设计(需求分析→估算→核心模块→深入讨论的四步法)、四个最常考的系统设计题的解法(短链系统/消息队列/CDN/分布式缓存)、设计中必须掌握的核心概念(一致性哈希/分库分表/读写分离/限流熔断),以及如何从课本知识过渡到能实际设计系统的思维方式。
系统设计面试是大多数应届生最没准备好的环节。
算法题可以刷,背面经可以准备,但系统设计考的是“你真的理解这个系统为什么这样设计”——靠死记硬背不管用,靠理解才行。本文给你一个可操作的框架。
系统设计面试考什么
面试官不在乎你给出一个"正确答案"
——系统设计没有唯一正确答案
面试官在乎的是:
1. 你能不能把模糊的需求转化成技术问题?
2. 你在设计时是否考虑了关键约束(性能/可用性/一致性)?
3. 你知不知道各种方案的优缺点和适用场景?
4. 面对 follow-up 问题,你能不能深入讨论细节?
常见系统设计题:
设计一个短链服务(bit.ly)
设计一个消息队列(Kafka)
设计一个分布式缓存(Redis 集群)
设计一个秒杀系统
设计微博/Twitter 的时间线功能
设计一个文件存储系统(Dropbox)
设计一个 CDN
设计一个限流系统
四步法:45 分钟内完成一个系统设计
第一步:需求分析(5-8 分钟)
面试官给的题目往往很模糊:
"设计一个 URL 短链服务"
你要做的:把模糊需求变成具体约束
必须问的问题:
功能需求:
用户能做什么?(生成短链、点击跳转、查看统计?)
有没有自定义短链的需求?
短链有没有过期时间?
非功能需求(更重要):
日活用户规模?(100万 vs 1亿,差一个数量级设计完全不同)
读写比例?(短链服务:读 >> 写,100:1 很正常)
可用性要求?(99.9% vs 99.999%,差别巨大)
一致性要求?(是否允许短暂数据不一致?)
例:短链服务需求确认后
功能:生成短链(URL → 短码)、点击跳转(短码 → 原URL)
规模:日活 100 万用户,每天 1 亿次跳转,每天 100 万次创建
可用性:99.9%(允许每年约 8 小时不可用)
一致性:最终一致性(允许短暂不一致)
第二步:容量估算(3-5 分钟)
做估算的目的:帮助选择合适的技术方案
短链服务估算示例:
存储:
每天 100 万条新短链
每条记录大约 500 字节(短码 + 原URL + 元数据)
3 年保留期:100万 × 365 × 3 × 500B ≈ 500GB
→ 普通关系数据库就能存,不需要分库分表
带宽:
读 QPS:1亿次/天 ÷ 86400秒 ≈ 1160 QPS(峰值 3x = 3500 QPS)
写 QPS:100万次/天 ÷ 86400秒 ≈ 12 QPS
→ 读多写少,需要缓存
响应时间目标:
跳转:< 10ms(用户体验关键)
生成:< 100ms
结论:需要缓存(Redis),不需要分布式数据库
第三步:高层设计(15-20 分钟)
核心:画出主要组件和数据流
短链服务的组件:
┌──────────┐ ┌──────────────┐ ┌──────────┐
│ 用户 │──请求──▶│ API Gateway │──────▶│ 短链服务 │
└──────────┘ │ (限流/鉴权) │ └─────┬────┘
└──────────────┘ │
┌────┴─────┐
│ Redis │ ← 缓存热点短链
└────┬─────┘
│ miss
┌────▼─────┐
│ MySQL │ ← 持久化存储
└──────────┘
主要接口:
POST /api/shorten
请求:{ "url": "https://..." }
返回:{ "short_code": "abc123", "short_url": "https://short.ly/abc123" }
GET /{short_code}
返回:HTTP 301/302 重定向到原 URL
核心算法(短码生成):
方案A:随机生成(6位 Base62 字符 = 56 亿种可能)
→ 简单,但要处理冲突
方案B:哈希(MD5/SHA1 取前几位)
→ 确定性,但有冲突风险
方案C:自增 ID + Base62 编码(推荐)
→ ID = 1000000 → Base62 = "4c92"
→ 天然唯一,无冲突
第四步:深入讨论(10-15 分钟)
面试官会 follow-up,例如:
Q:"如果短链服务要支持 10 倍规模呢?"
A:
数据库层:读写分离(一主多从)→ 再大可以分库分表
缓存层:Redis 集群,热点数据缓存命中率 > 99%
服务层:无状态,水平扩展
静态资源:CDN 分发
Q:"如何保证高可用?"
A:
多地部署(主备或双活)
数据库故障自动切换(MHA/Orchestrator)
限流熔断(防止下游故障雪崩)
优雅降级(缓存挂了,直接查数据库,性能降低但不中断)
Q:"如何统计短链点击次数?"
A:
方案1:直接写数据库(高频写,成为瓶颈)
方案2:写 Redis,定期刷到 MySQL(推荐)
方案3:写 Kafka,消费者异步更新(最好,但复杂度高)
必须掌握的核心概念
1. 一致性哈希(分布式缓存必考)
问题:Redis 集群有 3 个节点,如何决定 Key 放在哪个节点?
朴素方案:hash(key) % 3
问题:增加/删除节点时,几乎所有 Key 都要重新分配(缓存雪崩)
一致性哈希的解法:
把所有可能的 hash 值(0 ~ 2^32-1)排成一个环
节点也映射到环上
Key 顺时针找到第一个节点 → 该节点负责这个 Key
优点:增加/删除节点时,只有相邻节点的 Key 需要重新分配
加上虚拟节点:解决节点不均匀分布的问题
2. 读写分离
场景:读多写少的系统(90%读 + 10%写)
架构:
一主库(写)
多从库(读)
应用根据操作类型路由到主/从
注意主从延迟:
写完主库,读从库可能还没同步
→ 写后立即读:强制走主库
→ 对延迟不敏感的读:走从库
3. 限流算法
令牌桶(Token Bucket):推荐
桶里有令牌,处理请求消耗令牌,定速补充
允许一定的突发流量(桶里积攒的令牌)
漏桶(Leaky Bucket):
请求进队列,定速处理(平滑输出)
不允许突发,对下游保护更强
滑动窗口:
统计滑动时间窗口内的请求数
比固定窗口更平滑
实现选择:
单机:Java Guava RateLimiter(令牌桶)
分布式:Redis + Lua 脚本(原子操作保证准确)
4. 缓存策略
Cache Aside(旁路缓存):最常用
读:先查缓存,miss 了查数据库,再写回缓存
写:先更新数据库,再删除缓存
→ 删缓存不更新缓存:防止并发写的脏数据问题
Write Through:
写数据库时同步更新缓存
→ 强一致,但写性能下降
Write Behind(异步写回):
先更新缓存,异步更新数据库
→ 写性能最好,但有数据丢失风险
缓存穿透(查不存在的数据):
→ 缓存空值 或 布隆过滤器(Bloom Filter)
缓存击穿(热点 Key 失效):
→ 分布式锁或互斥锁(只让一个请求重建缓存)
缓存雪崩(大量 Key 同时失效):
→ 过期时间加随机抖动(+0~10分钟随机)
四个经典系统设计题解析框架
秒杀系统(最常考)
核心挑战:瞬间 100 万并发请求 1000 件商品
解决思路:
1. 前端:页面静态化(CDN),按钮置灰防重复点击
2. 网关:限流(每秒只放 X 个请求到下游)
3. Redis:预减库存(原子操作 DECR,负数则秒杀失败)
4. 消息队列:成功减库存的请求发到 Kafka,异步创建订单
5. 数据库:仅由消费者异步写,不承受高并发
关键点:
库存存 Redis,数据库不直接承压
超卖问题:Redis DECR 原子操作,判断 < 0 则失败
幂等性:同一用户多次点击,只能秒杀一次(Redis set NX)
消息推送(微博/Twitter 时间线)
核心挑战:明星 1000 万粉丝,发一条微博 → 1000 万条记录写入
推模式(Push):发博时写入所有粉丝的 Feed
优点:读很快(从自己的 Feed 表读)
缺点:大 V 发博时写放大严重(1条→1000万条)
拉模式(Pull):读时从关注的人的博文表合并
优点:写简单
缺点:读时需要合并大量数据,延迟高
推拉结合(最优):
普通用户:推模式
大 V(超过 X 粉丝):拉模式
读时:自己的 Feed 表(推) + 关注的大 V 实时拉取 → 合并排序
面试时的表达技巧
1. 大声说出你的思考过程
面试官看不到你的脑子,你的分析过程比结论更重要
"我考虑两种方案,方案A的优点是..缺点是..方案B..."
2. 先整体再细节
不要一开始就深入某个组件(面试官会认为你只会这一点)
先给出高层架构,确认面试官认可后,再深入某个部分
3. 主动说出你知道的权衡
"这里用 MySQL 是因为数据量不大,如果规模增长到 10x,
需要考虑分库分表,那时候可以用..."
→ 展示你懂得权衡,而不只是给一个"最好的"方案
4. 画图(白板或纸)
系统设计必须画架构图,口头描述很难让面试官跟上
5. 量化你的说法
不要说"很多请求",说"每秒 10000 QPS"
不要说"响应很快",说"P99 延迟 < 100ms"
推荐的学习资源
书:
《System Design Interview》(Alex Xu)
→ 最直接的面试准备书,有大量经典题目的完整解析
《数据密集型应用系统设计》(DDIA)
→ 深度理解分布式系统原理,进阶必读
网站:
System Design Primer(GitHub 开源,中文版也有)
→ github.com/donnemartin/system-design-primer
YouTube 频道:
"Gaurav Sen" 和 "ByteByteGo"
→ 每个视频讲一个系统设计问题,视频 + 动画非常直观
练习:
在纸上设计 → 讲给同学听 → 看标准答案对比
找同学模拟面试(最有效的练习方式)
小结
系统设计能力不是天生的,是通过大量的阅读、思考和练习积累的。大一大二时读 DDIA,了解分布式系统的核心问题;大三开始做设计练习,用四步法(需求→估算→设计→深入)反复训练;大四面试时就能游刃有余。
最后一个建议:系统设计的学习,从“我为什么需要这个技术”开始比“这个技术怎么用”更有效。知道了 Redis 集群解决什么问题,再学它的实现,才会真正理解而不是死记硬背。
