系统设计方法
系统设计到底要产出什么?
- 系统设计: 为满足业务需求定义架构、接口和数据组织,从基础设施到状态流转形成可解释的整体;
- 目标: 不是罗列组件名,而是说明请求怎样完成、数据怎样保持正确、规模和故障怎样处理;
- 早期价值: 明确难以轻易改变的边界,使后续演进有依据;
- 面试特点: 题目通常开放且模糊,考查需求沟通与权衡,不存在唯一标准拓扑;
怎样先明确需求和范围?
| 类别 | 要回答的问题 |
|---|---|
| 功能需求 | 哪些角色执行哪些操作,边界情况是什么? |
| 非功能需求 | 延迟、可用性、持久性、安全和规模目标是多少? |
| 扩展需求 | 统计、监控、推荐等哪些是本轮必须,哪些可以后续处理? |
- 约束优先: 明确冲突目标的优先级,例如数据不能丢与写入不能等待并非总能同时满足;
- 案例边界: 后续五篇是教学系统设计,不代表同名公司的真实完整实现或最新产品限制;
如何从业务量估算容量?
平均 RPS = 每日操作数 / 86400
逻辑新增存储 = 事件数 × 平均事件字节数
总存储 = 保留量 × 副本与派生数据系数 + 索引及元数据
平均带宽 = 时间段内传输字节数 / 秒数
缓存 = 活跃唯一键数 × 每项实际内存占用 × 副本数
- 单位: 案例统一使用十进制 KB、MB、GB、TB、PB,网络字节率乘 8 才是 bit/s;
- 峰值: 平均值仅是基线,还要估算突发、地区集中、并发连接和重试放大;
- 方向: 写入带宽、读取带宽和内部复制带宽分开计算,不能拿入口带宽充当总网络预算;
- 假设: DAU、读写比、对象大小与保留期来自题设,应逐项确认并做敏感性分析;
如何从数据模型形成 API 与组件边界?
- 数据模型: 先列实体、关系、唯一键和主要访问路径,让数据流清楚再决定存储方案;
- API: 定义输入、输出、错误、分页、身份和幂等语义,不需要先实现代码;
- 高层设计: 画出客户端到数据的完整路径,说明各组件为何存在及其状态归属;
- 详细设计: 选择关键瓶颈展开缓存、分片、同步或异步流程,并解释替代方案的代价;
怎样检查设计是否真正闭环?
- 故障检查: 逐一问入口、服务、数据库、缓存和消息系统失效时会怎样,是否存在单点或数据丢失窗口;
- 容量检查: 剩余副本能否承接故障流量,扩容是否只是把瓶颈推向下游;
- 证据表达: 明确已知、假设与尚待压测的部分,避免“SQL 无法扩展”等无条件判断;
- 演进检查: 只有当边界或瓶颈需要时再增加服务、分片和治理机制;
学完案例后怎样继续积累设计判断?
- 学习路径: 原文推荐 Kleppmann 的分布式系统课程、系统设计面试书、Chris Richardson 的微服务资料,以及 Serverless 和 Kubernetes 延伸主题;
- 工程材料: 跟进 Microsoft、Google、Netflix、AWS、Meta、Uber、Airbnb、GitHub、Intel、LinkedIn、PayPal、Twitter 等工程文章,关注问题和约束而非仅抄架构图;
- 实践: 参与新项目并向有经验的工程师复盘,在真实流量和故障中检验假设;
- 参考索引: 原文末尾汇集 Cloudflare、IBM、Fastly、NS1、DesignGurus、System Design Primer、AWS、Microsoft、Martin Fowler、PagerDuty、VMware 等资料,并提供 Excalidraw 图源;
- 阅读边界: 这些是原文的后续阅读入口,本轮未把外链中的完整课程当作已阅读材料,完整链接见本目录根 README 的原文入口;