系统设计模板
系统设计面试的通用思路与模板
设计方法论
四步法
┌─────────────────────────────────────────────────────────────┐
│ 系统设计四步法 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 需求澄清 (5-10 min) │
│ - 功能需求:核心功能是什么? │
│ - 非功能需求:性能、可用性、一致性要求 │
│ - 规模估算:用户量、数据量、QPS │
│ │
│ 2. 高层设计 (10-15 min) │
│ - 绘制系统架构图 │
│ - 确定核心组件 │
│ - 定义 API 接口 │
│ │
│ 3. 详细设计 (15-20 min) │
│ - 数据模型设计 │
│ - 核心算法/流程 │
│ - 关键组件深入 │
│ │
│ 4. 扩展讨论 (5-10 min) │
│ - 扩展性方案 │
│ - 容错处理 │
│ - 监控告警 │
│ │
└─────────────────────────────────────────────────────────────┘规模估算
常用数据:
- 1 天 = 86,400 秒 ≈ 100,000 秒
- 1 年 ≈ 365 天
- QPS 峰值 ≈ 平均 QPS × 2~3
存储估算:
- 1 KB = 1,000 字节
- 1 MB = 1,000 KB
- 1 GB = 1,000 MB
- 1 TB = 1,000 GB
网络带宽:
- 1 Gbps = 125 MB/s
- 单机 MySQL QPS ≈ 1,000~5,000
- 单机 Redis QPS ≈ 100,000
示例计算:
DAU = 1000万
每人每天 10 次请求
总请求 = 1亿/天
平均 QPS = 1亿 / 86400 ≈ 1,200
峰值 QPS ≈ 3,600通用架构模式
1. 读写分离
┌─────────────────────────────────────────────────────────────┐
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Client │ │ Client │ │ Client │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ └────────────────┼────────────────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │ Gateway │ │
│ └──────┬──────┘ │
│ │ │
│ ┌───────────────┼───────────────┐ │
│ │ 写 │ 读 │ │
│ ┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐ │
│ │ Master │──▶│ Slave 1 │ │ Slave 2 │ │
│ │ (写库) │ │ (读库) │ │ (读库) │ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
适用场景:读多写少
注意事项:主从延迟、数据一致性2. 缓存架构
┌─────────────────────────────────────────────────────────────┐
│ 缓存策略 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Cache-Aside(旁路缓存): │
│ 读:先读缓存 → 未命中 → 读 DB → 写缓存 │
│ 写:更新 DB → 删除缓存 │
│ │
│ Read-Through: │
│ 读:只读缓存,缓存负责从 DB 加载 │
│ │
│ Write-Through: │
│ 写:写缓存,缓存同步写 DB │
│ │
│ Write-Behind: │
│ 写:写缓存,缓存异步写 DB │
│ │
└─────────────────────────────────────────────────────────────┘
多级缓存:
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Browser │ → │ CDN │ → │ Redis │ → │ MySQL │
│ Cache │ │ │ │ │ │ │
└─────────┘ └─────────┘ └─────────┘ └─────────┘3. 消息队列
┌─────────────────────────────────────────────────────────────┐
│ 消息队列架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 同步调用(问题): │
│ A → B → C → D (链路长、耦合高、可用性差) │
│ │
│ 异步解耦: │
│ ┌───┐ ┌─────────┐ ┌───┐ │
│ │ A │ → │ MQ │ → │ B │ │
│ └───┘ │ │ ├───┤ │
│ │ │ → │ C │ │
│ │ │ ├───┤ │
│ │ │ → │ D │ │
│ └─────────┘ └───┘ │
│ │
│ 应用场景: │
│ - 异步处理:注册后发送邮件 │
│ - 削峰填谷:秒杀订单 │
│ - 服务解耦:订单 → 库存、积分、通知 │
│ │
└─────────────────────────────────────────────────────────────┘4. 分库分表
┌─────────────────────────────────────────────────────────────┐
│ 分库分表策略 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 垂直拆分(按业务): │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 用户表 │ │ 用户库 │ │ 订单库 │ │
│ │ 订单表 │ → │ 用户表 │ │ 订单表 │ │
│ │ 商品表 │ └─────────┘ │ 商品表 │ │
│ └─────────┘ └─────────┘ │
│ │
│ 水平拆分(按数据): │
│ ┌─────────────┐ ┌────────┐ ┌────────┐ │
│ │ 订单表 │ │订单表_0│ │订单表_1│ │
│ │ 1亿条数据 │ → │ 5000万 │ │ 5000万 │ │
│ └─────────────┘ └────────┘ └────────┘ │
│ │
│ 分片策略: │
│ - 范围分片:id 0-1000万 → db0,1000万-2000万 → db1 │
│ - 哈希分片:hash(user_id) % 4 │
│ - 一致性哈希:虚拟节点 │
│ │
└─────────────────────────────────────────────────────────────┘经典场景模板
短链系统
需求:
- 长 URL → 短 URL
- 短 URL → 长 URL(重定向)
- QPS: 10万生成/天,1000万访问/天
架构:
┌─────────┐ ┌───────────┐ ┌─────────┐ ┌─────────┐
│ Client │ → │ Gateway │ → │ Redis │ → │ MySQL │
└─────────┘ └───────────┘ │ (缓存) │ │ (持久化)│
└─────────┘ └─────────┘
核心设计:
1. 短码生成:
- 自增 ID + Base62 编码
- 预生成 ID 池
2. 存储:
- MySQL: short_code, long_url, created_at
- Redis: short_code → long_url
3. 重定向:
- 301 永久重定向(可缓存)
- 302 临时重定向(可统计)
API:
POST /shorten { "url": "https://..." }
GET /{code} → 302 重定向秒杀系统
需求:
- 短时间高并发抢购
- 库存扣减准确
- 防止超卖
架构:
┌─────────────────────────────────────────────────────────────┐
│ │
│ ┌─────────┐ ┌───────┐ ┌───────┐ ┌───────────┐ │
│ │ CDN │ → │ Nginx │ → │ App │ → │ Redis │ │
│ │(静态页面)│ │(限流) │ │Server │ │(库存/令牌)│ │
│ └─────────┘ └───────┘ └───────┘ └───────────┘ │
│ │ │
│ ┌───────────────▼───────────┐ │
│ │ MQ │ │
│ │ (异步处理订单) │ │
│ └───────────────┬───────────┘ │
│ │ │
│ ┌───────────────▼───────────┐ │
│ │ 订单服务 │ │
│ │ (创建订单、扣库存) │ │
│ └───────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
核心设计:
1. 前端:
- 静态页面 CDN 缓存
- 按钮置灰防重复点击
- 验证码/答题
2. 接入层:
- Nginx 限流
- 用户频率限制
3. 服务层:
- Redis 预扣库存(原子操作)
- 令牌桶/漏桶限流
- 请求入队列
4. 数据层:
- 库存扣减用 Lua 脚本
- 最终一致性
库存扣减 Lua 脚本:
if redis.call('get', KEYS[1]) >= ARGV[1] then
return redis.call('decrby', KEYS[1], ARGV[1])
else
return -1
end消息推送系统
需求:
- 实时推送消息
- 支持百万级在线用户
- 消息可靠送达
架构:
┌─────────────────────────────────────────────────────────────┐
│ │
│ ┌─────────┐ ┌───────────┐ ┌───────────────────────┐ │
│ │ 业务系统 │ → │ MQ │ → │ 推送服务 │ │
│ └─────────┘ └───────────┘ │ (连接管理、消息分发) │ │
│ └───────────┬───────────┘ │
│ │ │
│ ┌───────────────────┼──────────┐ │
│ │ │ │ │
│ ┌───────▼────┐ ┌──────▼─────┐ │ │
│ │ WebSocket │ │ APNS/ │ │ │
│ │ 连接池 │ │ FCM │ │ │
│ └───────┬────┘ └────────────┘ │ │
│ │ │ │
│ ┌───────────────┼───────────────┐ │ │
│ │ │ │ │ │
│ ┌───▼───┐ ┌───▼───┐ ┌───▼───┐ │ │
│ │Client │ │Client │ │Client │ │ │
│ └───────┘ └───────┘ └───────┘ │ │
│ │ │
└─────────────────────────────────────────────────────────────┘
核心设计:
1. 连接管理:
- 长连接(WebSocket)
- 心跳检测
- 断线重连
2. 消息存储:
- 离线消息队列
- 消息已读状态
3. 投递策略:
- 在线推送
- 离线存储 + 上线拉取
- 推拉结合
4. 可靠性:
- 消息 ACK
- 重试机制
- 去重分布式 ID 生成
方案对比:
┌────────────┬─────────────┬─────────────┬─────────────┐
│ 方案 │ 优点 │ 缺点 │ 适用场景 │
├────────────┼─────────────┼─────────────┼─────────────┤
│ UUID │ 简单、无依赖 │ 无序、太长 │ 低频、非主键 │
│ 自增 ID │ 有序、简单 │ 单点、暴露量│ 单体应用 │
│ 号段模式 │ 数据库依赖低│ 需要预生成 │ 中等规模 │
│ Redis │ 性能高 │ 依赖 Redis │ 高并发 │
│ 雪花算法 │ 有序、高性能│ 时钟回拨 │ 分布式 │
└────────────┴─────────────┴─────────────┴─────────────┘
雪花算法:
┌─────────────────────────────────────────────────────────────┐
│ 0 │ 时间戳(41位) │ 机器ID(10位)│ 序列号(12位)│
│ │ 约69年 │ 1024台机器 │ 4096/毫秒 │
└─────────────────────────────────────────────────────────────┘
时钟回拨处理:
1. 抛异常,等待时钟追上
2. 使用备用机器 ID
3. 使用 NTP 服务器同步非功能需求清单
| 维度 | 关注点 | 常见方案 |
|---|---|---|
| 性能 | QPS、延迟 | 缓存、异步、CDN |
| 可用性 | SLA 99.9%? | 冗余、故障转移、限流 |
| 扩展性 | 水平扩展 | 无状态、分片 |
| 一致性 | 强/最终一致 | 分布式事务、消息队列 |
| 安全性 | 认证、加密 | OAuth、HTTPS、WAF |
| 可观测性 | 日志、监控 | ELK、Prometheus |
| 成本 | 预算限制 | 弹性伸缩、资源优化 |