Skip to content

系统设计总览与心智

学系统设计最大的障碍不是「方案不会」,是根本不知道该从哪儿开始想。面试官说「设计一个 Twitter」,新手第一反应是画一个 Spring Boot + MySQL + Redis 的图,然后开始填字段——这就错了 90%。系统设计不是「拼组件」,是先搞清楚问题大小,再决定要不要用重武器。这一篇不讲任何具体方案,只讲一件事:面对「设计 X」时,脑子里到底应该先转什么

一句话先记住:系统设计 = 把模糊需求翻译成"流量数字 + 数据模型 + 失败假设"三件套,再选最便宜的方案撑住。看上去答案是架构图,实际上 80% 的工作发生在画图之前——没估算清楚 QPS 的架构都是空中楼阁,你不知道每秒 100 请求和每秒 100 万请求是两个完全不同的世界。


一、系统设计的本质:用约束反推方案

CRUD 应用没有「设计」一说——表建好、接口写好、上线。系统设计开始的边界点很清晰:当流量、数据、延迟、可用性中任何一个达到单机扛不住的量级,你就被迫离开 CRUD,进入设计。

设计的本质是在约束里找最便宜的可行解。约束有四类:

约束关键问题
流量每秒多少读 / 多少写?峰值是均值的几倍?
数据存什么、存多大、留多久、怎么查?
延迟用户能等多久?p99 多少?跨地域怎么算?
可用性能不能挂?挂多久?挂了影响多少用户?

真正的工作流是:先问需求 → 推算约束 → 在约束下选方案,而不是反过来——「先用 Redis Cluster 再倒推为什么要用」就是新手最常见的错误。架构师的功夫,80% 在前两步,只有 20% 在画图。


二、从模糊需求到清晰约束:四步法

面试官扔来一句「设计一个微博」,你不应该直接动笔,应该按这四步问回去:

2.1 第一步:功能边界(做什么、不做什么)

「设计微博」太大,先砍枝:

  • 用户发推、看 timeline、关注 / 取关——做
  • 评论、点赞——做
  • 私信、广告、推荐算法——这一轮不做
  • 视频、直播、电商——这一轮不做

这一步不是偷懒,是把无限的问题变成有限的问题。面试 45 分钟讨论不完整个微博,不画边界你必输。真实工作里也一样,做减法是架构师最重要的能力

2.2 第二步:非功能需求(数字)

砍完功能,问数字:

  • DAU(日活)是 1 万、100 万还是 1 亿?
  • 写多还是读多?读写比 1:1 还是 1:1000?
  • 数据要保留多久?
  • 全球还是单地区?
  • 容忍多少秒不可用?

这些数字直接决定架构等级。1 万 DAU 单机 + 一个 Redis 就够了;1 亿 DAU 必须分库分表 + 多机房 + CDN。

2.3 第三步:容量估算(下一篇专讲)

把数字翻成 QPS、存储、带宽。一个简化心算:

DAU × 人均请求数 / (24 × 3600) = 平均 QPS
平均 QPS × 5 = 峰值 QPS(常用倍数,具体业务调整)

例:1 亿 DAU,人均 50 次请求 → 平均 5.8 万 QPS → 峰值 30 万 QPS。有这个数字,后面所有"用什么 DB"都有根据

2.4 第四步:核心数据模型

不写表结构,只问三件事:

  1. 核心实体是什么?(微博:User / Tweet / Follow / Timeline)
  2. 数据访问模式是什么?(主要是按 user_id 查 timeline,不是全表扫描)
  3. 量级在哪?(Tweet 表一年 100 亿行,Follow 表一年 10 亿行)

数据模型的关键不是「字段叫什么」,是**「访问模式」+「量级」决定了后面要不要分库分表 / 用 KV / 加缓存**。同样一个 Tweet 表,1 万行你怎么写都行,100 亿行你写错一个索引就爆。


三、设计要展示的是「演进」,不是「终极版」

新手最常见的另一个错误是直接画 Kafka + Cassandra + Spark 的全家桶。这个图不解决任何问题,因为你没说清楚「为什么需要这些」。

正确的做法是从最简单开始,逐步暴露瓶颈,再升级:

V1: 单机
    user 表、tweet 表、follow 表都在一台 MySQL
    扛得住:DAU < 10 万

V2: 加缓存 + 读写分离
    热点 timeline 进 Redis,MySQL 一主多从
    扛得住:DAU 100 万

V3: 分库分表 + 异步 fanout
    Tweet 按 tweet_id 分,User 按 user_id 分
    发推后异步推到关注者收件箱(Push 模型)
    扛得住:DAU 1000 万

V4: 推拉结合 + 多机房
    大 V 用 Pull(实时拉),普通用户用 Push
    多机房读写,异地多活
    扛得住:DAU 1 亿+

每一步升级都要说清楚:V1 是什么瓶颈卡住的,V2 才合理出现。比如「V1 的 timeline 查询要 join 100 万条 follow,单机 MySQL 撑不住,所以 V2 加 Redis」。这种演进式答题,面试官立刻看出你懂工程——而不是背了一个图。


四、四个永远要回答的「关键取舍」

每个设计决策背后都有取舍,讲不出取舍的设计就是抄答案:

4.1 一致性 vs 可用性(CAP)

  • 强一致(转账、库存):宁可不可用,不能多扣钱 → 选 CP
  • 最终一致(微博点赞、关注数):稍微不一致没事,要可用 → 选 AP

4.2 读优化 vs 写优化

  • 读多写少(微博 timeline、新闻):写时多做事(预计算、推 fanout),读时拿现成的
  • 写多读少(日志、监控):写时只追加,读时再算

4.3 同步 vs 异步

  • 关键路径(下单、扣款):同步,失败立即返回错误
  • 可补偿路径(发邮件、通知、统计):异步走 MQ,失败重试

4.4 存储成本 vs 计算成本

  • 算一次存起来重复读(预计算 timeline)= 多花存储,省 CPU
  • 每次请求实时算 = 省存储,多花 CPU

任何一个方案上面都能套这四对。面试时把取舍讲明白,比方案本身重要——因为方案永远不止一个,但清晰的取舍说明你知道为什么选它


五、失败假设:「会挂」是设计前提,不是设计后想

CRUD 思维默认「东西不会挂」,系统设计反过来:默认所有东西都会挂,只是早晚。设计时永远要问:

组件它挂了会怎样?对策?
单台 Web 服务器流量切到其他 → 多副本 + LB
MySQL 主库写不了 → 自动切主、半同步复制
Redis缓存击穿打爆 DB → 多级缓存 + 限流 + 熔断
MQ消息堆积或丢 → 持久化 + 重试 + 死信队列
整个机房全挂 → 多机房 + DNS 切换
网络分区一半节点联不上 → 共识算法或可降级模式

没考虑过失败的设计,是危险的设计。真实事故的诱因 90% 都是「我们没想到这个会挂」。


六、系统设计的三种深度,三种岗位

不是所有「系统设计」都一个量级,粗分三层:

L1 「能跑」    单机 / 简单缓存 / 一两台服务器
              CRUD 工程师能做,DAU < 10 万

L2 「扛得住」  分库分表 / 多级缓存 / MQ 异步 / 限流
              中级后端的核心战力,DAU < 1000 万

L3 「永远在」  多机房 / 异地多活 / 容灾 / 全球分发
              架构师 / 高级,DAU 1 亿+,涉及组织协作

大多数面试问到 L2,大多数公司也只需要 L2。L3 是大厂少数核心系统的事(微信、淘宝、Twitter、Stripe),你不在那种岗位的话,精通 L2 就足以拿到 P7 / Senior。本系列重点是 L2,L3 在第四层简要带过。


七、画架构图的最少元素

无论多复杂的系统,架构图就这几个框:

┌─────────┐    ┌──────┐    ┌────────┐    ┌──────┐    ┌──────┐
│ Client  │ →  │ CDN  │ →  │  LB    │ →  │ App  │ →  │ DB   │
└─────────┘    └──────┘    └────────┘    └──────┘    └──────┘
                                            ↓             ↑
                                        ┌──────┐    ┌──────┐
                                        │ MQ   │ →  │Worker│
                                        └──────┘    └──────┘

                                        ┌──────┐
                                        │Cache │
                                        └──────┘

一个合格的架构图必须标清楚:

  • 每个箭头是同步还是异步
  • 每个组件的副本数 / 分片数
  • 数据流方向(读路径 / 写路径分开画)
  • 关键的 QPS / 延迟 / 容量数字

没有这些标注的架构图,和小学生画的没区别。架构图不是装饰,是「让别人 30 秒看懂你的设计取舍」的工具。


八、本系列的学习地图

01      总览(这篇)
02-05   心智:估算 / 演进 / CAP / 高可用
        看完知道"在想什么",不会再被问懵

06-13   抗压设施:LB / 缓存 / 分库 / MQ / 限流 / 一致性哈希
        这一段是面试和实战的"硬通货"

14-24   经典案例:短链 → IM → 秒杀 → 12306
        把上面的设施串起来设计真实系统
        每篇套同一个五段模板,可以模仿

25-30   进阶:多机房 / 容灾 / 灰度 / 设计文档
        大厂场景,按职业阶段决定看不看

优先级:01-13 强烈推荐每篇都看;14-24 选感兴趣的;25-30 按需。


九、踩坑提醒(总览版,后面每篇细讲)

  1. 不问需求就开始画图——做减法和定数字才是关键,画图只是产物
  2. 用名词堆代替推理——上来就 "ZooKeeper + Kafka + Cassandra",讲不出为什么
  3. 忽略容量估算——所有「需要 Redis 集群」「需要 MQ」的依据都来自数字,没数字纯靠感觉
  4. 画终极架构而不是演进——好设计是层层递进推出来的,不是从天而降的
  5. 不讨论失败模式——「这个组件挂了怎么办」必须每个都答得出
  6. 强一致和最终一致混淆——转账和点赞是两个世界,搞错就出大事
  7. 同步当异步用 / 反之——关键路径异步会丢数据,非关键路径同步会拖垮
  8. 不画读写路径分离——读写通常完全不同,一张图画不清楚
  9. 忽略「这个数据后期怎么扩」——MySQL 100 亿行不分库,后面是地狱
  10. 以为「系统设计」是一次画对——不是,是持续演进 + 持续重构

下一篇:02-容量估算.md,讲 QPS / 存储 / 带宽的快速心算法,常见数量级的「肌肉记忆」(1 亿 DAU = 多少 QPS?100 亿条记录占多少磁盘?),和为什么算错一个数量级会让整个架构错。

最后更新: