Skip to content

系统设计方法论

前言

系统设计不是拍脑袋画架构图,而是一套有章可循的方法论。 无论是面试中的系统设计题,还是实际工作中的架构设计,都遵循相似的思考框架:先搞清楚问题,再估算规模,然后设计方案,最后深入优化。

这篇文章会带你学什么?

学完这章后,你将获得:

  • 设计流程:掌握系统设计的四步法框架
  • 容量估算:学会"信封背面估算"的技巧
  • 常见模式:熟悉缓存、分库分表、消息队列等核心模式
  • 权衡思维:理解架构设计中的 trade-off 思维
  • 实战案例:通过短链服务、Feed 流等案例理解设计过程
章节内容核心概念
第 1 章设计四步法需求澄清、容量估算、架构设计、深入优化
第 2 章容量估算QPS、存储、带宽、信封背面估算
第 3 章核心设计模式缓存、分库分表、消息队列、CDN
第 4 章权衡思维一致性 vs 可用性、性能 vs 成本
第 5 章经典案例短链服务、Feed 流、秒杀系统

1. 系统设计四步法

系统设计不是一上来就画架构图。无论是面试还是实战,都应该遵循一个结构化的流程。

系统设计四步法
点击每个步骤查看详细内容
1
需求澄清
~5 分钟
2
容量估算
~5 分钟
3
架构设计
~15 分钟
4
深入优化
~10 分钟
需求澄清
不要急着画架构图。先搞清楚:系统要解决什么问题?用户规模多大?有哪些核心功能?有哪些非功能需求?
核心功能有哪些?(MVP 范围)
用户规模?DAU / QPS 预估
读写比例?读多写少还是写多读少?
数据量级?需要存多少数据?
可用性要求?几个 9?
延迟要求?P99 要多少毫秒?
示例(设计短链服务):
短链服务:生成短链(写)+ 重定向(读),读写比约 100:1,日均 1 亿次重定向,短链永不过期。

为什么要先澄清需求?

很多人拿到题目就开始画图,结果设计了一个"正确但不是面试官想要的"系统。花 5 分钟问清楚需求,能避免后面 30 分钟的返工。

常见的澄清问题:

  • 系统的核心功能是什么?(不要设计所有功能)
  • 用户规模多大?(决定是否需要分布式)
  • 读写比例?(决定缓存策略)
  • 数据需要保留多久?(决定存储方案)

2. 容量估算:信封背面的艺术

"信封背面估算"(Back-of-envelope estimation)是系统设计中的核心技能。不需要精确计算,只需要知道量级。

信封背面估算器
输入基础数据,自动计算系统容量需求
日请求量
2000.0 万
平均 QPS
231
峰值 QPS
693
日带宽
102.4 GB
峰值带宽
3.5 MB/s
常用估算参考值
1 天86,400 秒
1 月≈ 250 万秒
QPS 1000≈ 1 台 8 核服务器
1 亿/天≈ 1,200 QPS
MySQL 单机≈ 5,000 QPS
Redis 单机≈ 100,000 QPS

常用换算速查

量级换算记忆技巧
1 天86,400 秒≈ 10 万秒
1 亿请求/天≈ 1,200 QPS除以 10 万
1 KB × 1 亿≈ 100 GB1 亿条小记录
1 MB × 100 万≈ 1 TB100 万张图片

2-8 法则在估算中的应用

大多数系统遵循 80/20 法则:20% 的数据承载 80% 的请求。这意味着:

  • 缓存大小 ≈ 总数据量 × 20%
  • 热点 QPS ≈ 总 QPS × 80% 集中在 20% 的 key 上
  • 缓存命中率目标 ≈ 80%+(低于这个值说明缓存策略有问题)

3. 核心设计模式

系统设计中反复出现的模式,掌握这些就能应对大多数场景。

3.1 缓存模式

模式读路径写路径适用场景
Cache-Aside先查缓存,miss 则查 DB 并回填先写 DB,再删缓存通用场景,最常用
Read-Through缓存层自动从 DB 加载同 Cache-Aside需要缓存框架支持
Write-Behind同 Cache-Aside先写缓存,异步写 DB写密集型,可容忍丢数据

为什么是"删缓存"而不是"更新缓存"?

更新缓存在并发场景下容易出现数据不一致:线程 A 和 B 同时更新,A 先写 DB 但 B 先更新缓存,导致缓存中是 B 的旧值。删除缓存则让下次读请求重新从 DB 加载,天然避免这个问题。

3.2 分库分表

当单表数据量超过千万级,或单库 QPS 超过瓶颈时,就需要考虑分库分表。

策略做法优点缺点
垂直分库按业务域拆分数据库业务解耦,独立扩展跨库 JOIN 困难
水平分表同一张表按规则拆成多张单表数据量可控分片键选择关键
垂直分表把大字段拆到独立表减少 IO,提升查询效率需要额外 JOIN

分片键选择原则

  • 选择查询最频繁的字段(如 user_id)
  • 数据分布要均匀,避免热点
  • 尽量让同一用户的数据在同一分片(减少跨分片查询)

3.3 消息队列

消息队列是分布式系统的"减震器",核心作用是解耦、异步、削峰。

场景不用队列用队列
下单后发通知下单接口同步调用通知服务,通知失败导致下单失败下单成功后发消息,通知服务异步消费
秒杀抢购瞬间流量打爆数据库请求先入队列,后端按能力消费
数据同步服务 A 直接调用服务 B 的接口服务 A 发事件,服务 B 订阅处理

4. 权衡思维:没有银弹

架构设计的本质是权衡(Trade-off)。每个决策都有代价,关键是理解代价并做出适合当前阶段的选择。

权衡维度选项 A选项 B决策依据
一致性 vs 可用性强一致(CP)高可用(AP)业务能否容忍短暂不一致?
性能 vs 成本全量缓存按需缓存数据量和预算
简单 vs 灵活单体架构微服务团队规模和业务复杂度
实时 vs 批量流式处理批处理数据时效性要求
自建 vs 托管自己搭 MySQL用云数据库 RDS运维能力和成本

架构决策记录(ADR)

每个重要的架构决策都应该记录下来:背景是什么、考虑了哪些方案、为什么选了这个、有什么代价。这不是为了甩锅,而是为了让后来的人理解"为什么当时这么设计"。

格式很简单:

  • 标题:用 XXX 替代 YYY
  • 背景:我们遇到了什么问题
  • 决策:我们选择了什么方案
  • 理由:为什么选这个
  • 代价:这个决策的缺点和风险

常见的错误权衡

错误表现正确做法
过早优化日活 1000 就上分库分表先用单库,遇到瓶颈再拆
技术驱动"我想用 Kafka" 而不是 "我需要异步"从问题出发,而非从技术出发
忽略运维成本选了最优方案但团队维护不了方案要匹配团队能力
追求完美一致性所有场景都用分布式事务大多数场景最终一致性就够了

5. 经典案例

通过三个经典案例,把前面学到的方法论串起来。

5.1 短链服务(TinyURL)

短链服务是系统设计面试的经典题目,麻雀虽小五脏俱全。

需求澄清

  • 核心功能:长链接 → 短链接(写),短链接 → 重定向(读)
  • 读写比:约 100:1(读远多于写)
  • 日均重定向:1 亿次
  • 短链永不过期

容量估算

指标计算结果
写 QPS1 亿 / 100 / 86400≈ 12 QPS
读 QPS1 亿 / 86400≈ 1,200 QPS
峰值读 QPS1,200 × 3≈ 3,600 QPS
5 年存储100 万/天 × 365 × 5 × 100B≈ 18 GB
缓存(20%)18 GB × 20%≈ 3.6 GB

架构设计

写路径:客户端 → API Server → ID 生成器 → Base62 编码 → 写入 MySQL + Redis
读路径:客户端 → CDN → API Server → Redis 查询 → 302 重定向
                                    ↓ (cache miss)
                                  MySQL 查询 → 回填 Redis

关键设计决策

  • 短码生成:Snowflake 分布式 ID + Base62 编码,避免哈希冲突
  • 缓存策略:Cache-Aside,热点短链用 CDN 加速
  • 数据库:单表即可(18GB 很小),按短码做索引

5.2 Feed 流系统

社交平台的 Feed 流(朋友圈、微博首页)是另一个经典题目。

核心挑战:用户发一条动态,如何让所有关注者看到?

方案做法优点缺点
拉模式(Pull)读取时实时聚合关注者的动态写入简单,存储少读取慢,关注多时延迟高
推模式(Push)发布时写入所有粉丝的收件箱读取极快大 V 发动态写扩散严重
推拉结合普通用户推,大 V 拉平衡读写性能实现复杂

推拉结合方案

  • 粉丝数 < 1 万:发布时推送到所有粉丝的 Feed 缓存(推模式)
  • 粉丝数 > 1 万:不推送,粉丝读取时实时拉取(拉模式)
  • 用户打开 Feed 时:合并推送的内容 + 实时拉取大 V 的内容,按时间排序

5.3 秒杀系统

秒杀的核心挑战:瞬间超高并发 + 库存不能超卖。

流量特征

  • 活动开始前:大量用户刷新页面等待
  • 活动开始瞬间:QPS 可能是平时的 100 倍以上
  • 活动结束后:流量迅速回落

分层削峰策略

用户请求 → CDN(静态页面)→ 网关(限流)→ 消息队列(削峰)→ 库存服务(扣减)
层级策略效果
前端按钮置灰 + 随机延迟 + 验证码过滤机器人,分散请求
CDN静态资源缓存减少 90% 的页面请求
网关令牌桶限流只放行系统能承受的流量
消息队列请求入队,异步处理削峰填谷,保护数据库
库存服务Redis 预扣减 + Lua 原子操作防止超卖,毫秒级响应

秒杀的核心原则

  1. 尽量拦截在上游:能在 CDN 挡住的就不要到应用层
  2. 读写分离:商品详情页走缓存,只有下单走数据库
  3. 异步处理:用户点击"抢购"后立即返回"排队中",后台异步处理
  4. 兜底方案:限流、熔断、降级,任何一层出问题都有 Plan B

总结

系统设计是一门实践性很强的技能,核心在于结构化思考和权衡取舍。

回顾本章的关键要点:

  1. 四步法框架:需求澄清 → 容量估算 → 架构设计 → 深入优化,每一步都不可跳过
  2. 信封背面估算:不需要精确,只需要知道量级,用于指导架构决策
  3. 核心模式:缓存、分库分表、消息队列、CDN、限流熔断——这些是系统设计的"积木"
  4. 权衡思维:没有完美方案,只有适合当前阶段的方案,记录每个决策的理由和代价
  5. 经典案例:短链服务练基础、Feed 流练推拉模型、秒杀练高并发——掌握这三个就能举一反三

延伸阅读