系统设计基础
NOTE
本章节适用于有 4 年以上工作经验的候选人。如果你是应届生或初级工程师,可以跳过或略读。
核心概念
1. 可扩展性 (Scalability)
垂直扩展 (Scale Up):
- 增加单台服务器的容量(CPU、内存、磁盘)
- 简单但有上限
水平扩展 (Scale Out):
- 增加服务器数量
- 更复杂但理论上无上限
2. 负载均衡
将请求分发到多个服务器:
用户请求 → 负载均衡器 → 服务器集群常用算法:
- Round Robin(轮询)
- Least Connections(最少连接)
- IP Hash(IP 哈希)
3. 数据库扩展
读写分离:
主库(写) → 从库(读)
↘ 从库(读)分片 (Sharding):
- 按用户 ID 分片
- 按时间范围分片
- 按哈希分片
NoSQL:
- Key-Value(Redis、DynamoDB)
- Document(MongoDB)
- Column( Cassandra、HBase)
- Graph(Neo4j)
4. 缓存
缓存策略:
| 策略 | 说明 | 适用场景 |
|---|---|---|
| Cache-Aside | 应用自行管理缓存 | 读多写少 |
| Read-Through | 缓存自动加载 | 通用场景 |
| Write-Through | 写缓存同时写数据库 | 数据一致性要求高 |
| Write-Behind | 异步写入数据库 | 写入性能要求高 |
缓存淘汰算法:
- LRU(Least Recently Used)
- LFU(Least Frequently Used)
- FIFO(First In First Out)
5. 消息队列
解耦和异步处理:
生产者 → 消息队列 → 消费者常用中间件:
- RabbitMQ
- Apache Kafka
- Amazon SQS
- Redis Pub/Sub
设计流程
Step 1: 理解问题与范围
- 明确功能需求
- 询问用户规模(DAU、并发量)
- 确定性能要求(延迟、吞吐量)
- 定义成功标准
Step 2: 粗略设计
- 画出核心组件
- 明确数据流
- 识别瓶颈
Step 3: 深入设计
- API 设计
- 数据库 Schema
- 缓存策略
- 扩展方案
Step 4: 权衡与讨论
- 可用性 vs 一致性
- 复杂度 vs 性能
- 成本 vs 效率
常见系统设计题
1. 设计短链接服务
核心功能:
- 长链接 → 短链接
- 短链接 → 长链接跳转
关键组件:
长链接 → 哈希/自增ID → 短链接存储 → 短链接
短链接 → 查询 → 重定向到长链接存储选择:
- 数据库:MySQL、PostgreSQL
- NoSQL:Redis、DynamoDB
- 考虑用 MySQL + Redis 缓存
2. 设计推特/微博
核心功能:
- 发推文
- 获取时间线
- 关注/取消关注
关键挑战:
- 主页时间线的生成(推送给所有关注者开销大)
- 解决方案:Pull vs Push 模型
存储选择:
- 用户数据:MySQL
- 推文内容:对象存储(如 S3)
- 时间线缓存:Redis
3. 设计聊天系统
核心功能:
- 私信
- 群聊
- 在线状态
关键组件:
用户 → WebSocket → 消息服务 → 消息存储
↓
离线消息队列协议选择:
- WebSocket(实时)
- Long Polling(兼容)
- MQTT(IoT)
4. 设计搜索建议/自动补全
核心功能:
- 前缀匹配
- 热门推荐
- 个性化排序
关键组件:
前缀 → Trie 树 → 候选集 → 排序 → 返回存储选择:
- Trie 树(内存)
- Redis(缓存热门前缀)
- Elasticsearch(复杂搜索)
5. 设计限流器
核心功能:
- 限制 API 调用频率
- 防止滥用
算法选择:
| 算法 | 优点 | 缺点 |
|---|---|---|
| 计数器 | 简单 | 边界突刺 |
| 滑动窗口 | 平滑 | 实现复杂 |
| 令牌桶 | 支持突发 | - |
| 漏桶 | 稳定输出 | - |
CAP 定理
分布式系统最多只能同时满足两个:
- C (Consistency) - 一致性:所有节点数据一致
- A (Availability) - 可用性:每次请求都有响应
- P (Partition Tolerance) - 分区容错:网络分区时仍可运行
常见选择:
- CP(Redis、DynamoDB)
- AP(Cassandra、Eureka)
一致性哈希
解决数据分片时的负载均衡问题:
传统哈希:hash(key) % N → 服务器编号
↓
新增/删除服务器时大量数据需要迁移
一致性哈希:
- 将服务器和数据映射到同一个环上
- 数据顺时针找最近的服务器
- 新增/删除只影响局部数据虚拟节点:解决数据倾斜问题