← 返回思维链目录

系统设计权衡思维链

面试官让你设计一个系统,你脑子里怎么一步步想

1. 系统设计通用套路

现象面试官:"设计一个短链系统"
别上来就画架构图,先想清楚再画。
本质:系统设计不是"画多复杂的图",而是展示你的思考过程 —— 怎么拆解问题、怎么做取舍。每个决策说清"为什么这么选、不选另一个会怎样"。
直觉:先问清楚规模和需求,再估算,再选方案,最后考虑扩展和容灾。
🌊 六步走
① 澄清
先问清楚:核心功能?用户量?读多写多?延迟?一致性要求?→ 别假设,要问
功能/非功能需求读写比延迟/一致性
② 估算
信封背面计算:QPS?存储?带宽?→ 例:1 亿用户每天 10 次 → QPS ~1.2 万 → 决定要不要分库分表
QPS 估算存储估算峰值倍数
③ 建模
核心数据模型 + API:有哪些表?对外什么接口?→ 例:短链 = {短码, 长URL, 时间} + 生成/跳转 API
数据模型表设计REST API
④ 架构
分层架构:客户端→负载均衡→应用→数据→缓存/MQ → 画出来讲数据流向
负载均衡无状态应用读写分离
⑤ 难点
深入核心难点 + 权衡:最难的是什么?(短链发号/秒杀防超卖/Feed 推拉)→ 给 2-3 方案,讲取舍
核心难点方案对比权衡取舍
⑥ 扩展
扩展 + 容灾:流量翻 10 倍?(分库分表/微服务)→ 挂了?(主备/多机房/限流降级)
横向扩展分库分表高可用
关键:每个决策说清"为什么这么选、不选另一个会怎样"。面试官想看你的思考过程,不是答案。

2. 短链系统

案例设计 t.cn/xxx 短链系统
本质:长 URL 变短码,核心是"发号"(唯一短码)+ 缓存(读多写少)+ 重定向(跳转)。
🌊 顺藤摸瓜
① 发号
长 URL 怎么变短码? → ① 哈希(MD5 取前 6 位,有冲突);② 发号器(自增 ID 转 62 进制,唯一不冲突)→ 推荐
哈希方案发号器Base62 编码
② 跳转
用户点短链 → 查库 → 301/302 重定向 → 301 浏览器缓存(少查库)/ 302 每次统计点击
301 永久重定向302 临时点击统计
③ 缓存
读(跳转)远多于写(生成)→ 加 Redis 缓存 → 短码→长URL,命中直接返回不查库
读写比悬殊Redis 缓存布隆过滤器
④ 扩展
数据量大了?→ 短码分库分表(哈希分片)→ 发号器分布式(Snowflake 雪花 ID)
分库分表哈希分片Snowflake

3. 秒杀系统

案例100 件商品 10 万人抢
本质:秒杀 = 瞬间高并发抢有限库存。核心是让尽量少的请求碰到数据库 —— 限流挡住、缓存预减、异步削峰。
🌊 顺藤摸瓜
① 防超卖
"查库存-减库存"非原子 → 并发超卖 → ① DB 乐观锁(WHERE stock>0);② Redis 原子扣减(Lua DECR)
竞态条件DB 乐观锁Redis Lua
② 挡流量
10 万人不能全打 DB → 分层挡:① 前端防抖+验证码;② CDN 静态页;③ Nginx 限流;④ Redis 预减库存
前端防抖CDNNginx 限流Redis 预减
③ 异步
抢到的下单慢 → 异步 → MQ 削峰(抢到=发消息,消费者慢慢下单)→ 用户看到"排队中"
MQ 异步削峰消费者下单最终一致
④ 防刷
黄牛脚本抢 → ① 限购(用户ID+商品ID 唯一索引);② 风控识别机器人;③ IP/设备限频
唯一索引防重风控设备指纹
三板斧:限流(挡住)+ 缓存(预减)+ 异步(削峰)。核心:让尽量少的请求碰到 DB。

4. Feed 流:推 vs 拉

案例设计朋友圈 Feed 流
本质:一条动态要让所有粉丝看到。核心是"发的时候推给粉丝"还是"粉丝来的时候去拉"。
🌊 顺藤摸瓜
① 推(写扩散)
发布时推到所有粉丝收件箱 → 读时直接读自己收件箱(快)→ 问题:大 V 发一条推千万份,写放大
写扩散读快大 V 写放大
② 拉(读扩散)
发布只存自己主页,读时拉关注人最新 → 写快 → 问题:关注人多,读时要合并很多源,慢
读扩散写快读时聚合慢
③ 混合
普通人用推(粉丝少),大 V 用拉(粉丝多)→ 阈值切换(粉丝 > N 走拉)→ 微博/微信都这么干
推拉结合大 V 阈值实际方案

5. CAP:为什么不能全都要

现象分布式系统,一致性、可用性、分区容错为什么只能选两个?
本质:网络一定会断(分区 P 必选)。断了之后,要么牺牲一致性保可用,要么牺牲可用性保一致,只能二选一。
🌊 顺藤摸瓜
① CAP
P(分区)必选 → 只能 CP 或 AP → CP(银行转账,宁可不可用也不能数据错)/ AP(朋友圈点赞,可用优先,短暂不一致没事)
一致性 C可用性 ACP/AP 场景
② BASE
实际大多选 AP + BASE:基本可用 + 软状态 + 最终一致 → 允许短暂不一致,但最终会一致
BASE最终一致柔性事务

总结

环节脑子里想什么
澄清多大规模?读多写多?延迟?一致性?
估算QPS?存储?带宽?要不要分库分表?
建模什么表?什么 API?
架构负载均衡→应用→数据→缓存
难点最难的是什么?给方案+权衡
扩展流量翻 10 倍?挂了怎么办?
本质:系统设计 = "先想清楚,再画图"。没有完美方案,只有适合场景的权衡 —— 这才是系统设计的精髓。