Skip to content

第 6 章:系统设计 ​

📋 本章概述 ​

系统设计是软件工程师的核心能力,涉及需求分析、架构设计、技术选型、扩展性和可靠性等多个维度。本章将学习系统设计的方法论和常见模式,通过实际案例掌握设计大规模系统的能力。

学习目标 ​

完成本章后,你将能够:

  • ✅ 进行完整的需求分析
  • ✅ 设计系统架构
  • ✅ 进行合理的技术选型
  • ✅ 设计可扩展的系统
  • ✅ 保证系统高可用性
  • ✅ 进行系统性能估算
  • ✅ 设计优秀的 API

前置知识 ​

  • ✅ 掌握微服务架构
  • ✅ 理解数据库设计
  • ✅ 了解网络和分布式系统
  • ✅ 熟悉常见设计模式

1. 系统设计方法论 ​

1.1 系统设计流程 ​

标准流程(SNAKE 模型):

  1. Scope(明确范围) - 5分钟

    • 明确功能需求
    • 确定非功能需求
    • 定义边界条件
  2. Numbers(估算数据) - 5分钟

    • 用户规模
    • QPS(每秒查询数)
    • 存储需求
    • 带宽需求
  3. API(设计接口) - 5分钟

    • 核心 API 端点
    • 请求/响应格式
    • 认证授权方式
  4. Knowledge(技术选型) - 10分钟

    • 数据库选择
    • 缓存策略
    • 消息队列
    • 存储方案
  5. Expand(深入设计) - 15分钟

    • 详细架构图
    • 数据流程
    • 关键组件设计
    • 扩展性方案

1.2 非功能需求 ​

🏰 The Metaphor: The Giant vs The Army

  • Vertical Scaling (垂直扩展/Scale Up): 就像养一个巨人。如果活干不完,就给巨人吃更多饭(加 CPU/RAM),让他长得更大。
    • 优点: 简单,不需要改代码。
    • 缺点: 巨人总有长不到的时候(硬件极限),而且巨人病了(单点故障),活就没人干了。
  • Horizontal Scaling (水平扩展/Scale Out): 就像组建一支军队。如果活干不完,就招更多的普通士兵(加服务器)。
    • 优点: 理论上无限扩展,死几个士兵不影响大局(高可用)。
    • 缺点: 管理一支军队比养一个巨人难多了(分布式复杂性)。

可扩展性(Scalability):

  • 水平扩展 vs 垂直扩展
  • 无状态设计
  • 数据分片

高可用性(Availability):

  • 冗余设计
  • 故障转移
  • 负载均衡
  • 降级策略

一致性(Consistency):

  • 强一致性 vs 最终一致性
  • CAP 理论
  • 分布式事务

性能(Performance):

  • 响应时间
  • 吞吐量
  • 资源利用率

可靠性(Reliability):

  • 数据持久化
  • 备份恢复
  • 容错机制

2. 容量规划和估算 ​

2.1 估算方法 ​

常用换算:

1 Million = 10^6 = 1,000,000
1 Billion = 10^9 = 1,000,000,000

1 KB = 10^3 bytes = 1,000 bytes
1 MB = 10^6 bytes
1 GB = 10^9 bytes
1 TB = 10^12 bytes

1 天 = 86,400 秒 ≈ 100,000 秒

示例:Twitter 估算

假设:

  • 日活用户:200M
  • 每用户每天发 2 条推文
  • 平均推文大小:300 bytes
  • 读写比:100:1

计算:

写入 QPS = 200M * 2 / 86400 ≈ 4,600 QPS
峰值写入 QPS = 4,600 * 2 = 9,200 QPS

读取 QPS = 4,600 * 100 = 460,000 QPS
峰值读取 QPS = 920,000 QPS

每日存储 = 200M * 2 * 300 bytes = 120 GB/天
年存储 = 120 GB * 365 ≈ 44 TB/年(不含媒体)

2.2 性能目标 ​

响应时间:

  • Web 页面加载:< 1s
  • API 响应:< 100ms
  • 数据库查询:< 10ms

可用性:

  • 99.9%(three nines):每年 8.76 小时停机
  • 99.99%(four nines):每年 52.6 分钟停机
  • 99.999%(five nines):每年 5.26 分钟停机

3. 架构设计模式 ​

3.1 分层架构 ​

经典三层架构:

表示层(Presentation Layer)
   ↓
业务逻辑层(Business Logic Layer)
   ↓
数据访问层(Data Access Layer)
   ↓
数据库(Database)

优势:

  • 关注点分离
  • 易于维护
  • 可替换性

适用场景:

  • 传统 Web 应用
  • 企业级应用

3.2 微服务架构 ​

特点:

  • 服务独立部署
  • 去中心化治理
  • 按业务能力组织

挑战:

  • 分布式复杂性
  • 数据一致性
  • 服务治理

3.3 事件驱动架构 ​

核心概念:

  • 事件生产者
  • 事件消费者
  • 消息队列

优势:

  • 松耦合
  • 异步处理
  • 易于扩展

适用场景:

  • 实时数据处理
  • 异步工作流
  • 微服务通信

4. 数据存储设计 ​

4.1 数据库选择 ​

关系型数据库(PostgreSQL, MySQL):

  • ✅ 适合:结构化数据、事务要求高
  • ❌ 不适合:海量数据、高并发写入

NoSQL 数据库:

类型代表适用场景
文档MongoDB半结构化数据、快速迭代
键值Redis, DynamoDB缓存、会话存储
列族Cassandra, HBase时序数据、大规模写入
图Neo4j社交网络、推荐系统

4.2 数据分片(Sharding) ​

📚 The Metaphor: The Library Section 数据库分片就像是图书馆的分区。 如果所有的书都堆在一个房间里,找书的人会挤破头。 于是你把书按首字母分类:

  • A-M 的书放在东馆(Shard 1)。
  • N-Z 的书放在西馆(Shard 2)。

读者(查询)进门前,先看一眼索引(Routing),就知道该去哪个馆。 这样,两个馆可以同时接待读者,吞吐量翻倍。

🏛️ Scaling Patterns: Consistent Hashing & CAP Theorem

  • Consistent Hashing (一致性哈希): 解决分片扩容/缩容时的数据迁移问题。
    • 将数据和节点都映射到一个哈希环上。
    • 增加节点只影响相邻节点的数据,而不是全量重哈希 (Reshuffling)。
  • CAP Theorem: 在分布式系统中,Consistency (一致性), Availability (可用性), Partition Tolerance (分区容错性) 三者只能得其二。
    • CP: 强一致性 (Zookeeper, HBase)。网络分区时,拒绝服务。
    • AP: 高可用性 (Cassandra, DynamoDB)。网络分区时,返回旧数据 (最终一致性)。
    • P 是必须的 (网络必然会分区)。所以只能在 C 和 A 之间权衡。

分片策略:

1. 范围分片:

  • 按 ID 范围:1-1000 → Shard1, 1001-2000 → Shard2
  • 优点:简单
  • 缺点:数据分布可能不均

2. 哈希分片:

  • 按 ID 哈希:hash(user_id) % N
  • 优点:数据分布均匀
  • 缺点:难以范围查询

3. 地理分片:

  • 按地区:中国用户 → Shard-CN, 美国用户 → Shard-US
  • 优点:就近访问,低延迟
  • 缺点:跨区域查询复杂

4. 一致性哈希:

  • 解决节点增减时的数据迁移问题
  • 虚拟节点平衡负载

5. 缓存策略 ​

5.1 缓存模式 ​

🧠 The Metaphor: The Short-term Memory 缓存就像是你的短期记忆。 数据库是书本。

  • Cache-Aside: 老师问你问题。你先想一下(查缓存)。想不起来,就去翻书(查数据库),然后背下来(写入缓存),最后回答老师。
  • Write-Through: 你做笔记时,一边写在草稿纸上(缓存),一边立刻写在笔记本上(数据库)。很安全,但写得慢。
  • Write-Behind: 你先狂写在草稿纸上(缓存)。等下课了,再慢慢抄到笔记本上(数据库)。写得飞快,但如果草稿纸丢了(断电),笔记就没了。

Cache-Aside(旁路缓存):

读取:
1. 先查缓存
2. 缓存未命中,查数据库
3. 写入缓存
4. 返回数据

更新:
1. 更新数据库
2. 删除缓存

Read-Through:

  • 缓存层自动加载数据
  • 应用层不感知

Write-Through:

  • 同时写入缓存和数据库
  • 保证一致性

Write-Behind:

  • 先写缓存,异步写数据库
  • 性能好,但可能丢数据

5.2 缓存失效策略 ​

常见问题:

缓存穿透: 查询不存在的数据

  • 解决:布隆过滤器、缓存空值

缓存击穿: 热点数据过期

  • 解决:永不过期、互斥锁

缓存雪崩: 大量缓存同时过期

  • 解决:随机过期时间、多级缓存

6. API 设计 ​

6.1 RESTful API 设计 ​

资源命名:

✅ GET    /users          # 获取用户列表
✅ GET    /users/123      # 获取单个用户
✅ POST   /users          # 创建用户
✅ PUT    /users/123      # 更新用户(全量)
✅ PATCH  /users/123      # 更新用户(部分)
✅ DELETE /users/123      # 删除用户

❌ GET    /getUsers
❌ POST   /createUser
❌ POST   /users/delete/123

版本控制:

方式 1:URL 路径
GET /api/v1/users

方式 2:请求头
GET /api/users
Accept: application/vnd.myapi.v1+json

方式 3:查询参数
GET /api/users?version=1

分页:

GET /users?page=1&limit=20

响应:
{
  "data": [...],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 1000,
    "totalPages": 50
  }
}

6.2 GraphQL ​

优势:

  • 客户端控制数据结构
  • 单个请求获取多个资源
  • 强类型 Schema

劣势:

  • 学习曲线陡峭
  • 缓存复杂
  • 性能优化困难

7. 系统设计案例 ​

案例 1:设计 URL 缩短服务 ​

需求:

  • 长 URL 转短 URL
  • 短 URL 跳转到长 URL
  • 支持自定义短链
  • 统计访问次数

估算:

  • 每日新增:100M 短链
  • QPS:1,000(写),10,000(读)
  • 存储:100M * 365 * 100 bytes ≈ 3.65 TB/年

设计:

组件:
- API 服务器(负载均衡)
- 数据库(分片存储)
- 缓存(Redis)
- 计数器(Redis)

短 URL 生成:
方式 1:哈希(MD5/SHA256)+ 截取
方式 2:自增 ID + Base62 编码
方式 3:随机字符串 + 碰撞检测

数据库设计:
urls 表:
- id (主键)
- short_code (唯一索引)
- long_url
- user_id
- created_at
- expires_at

访问统计:
- Redis 计数器
- 异步写入数据库

案例 2:设计实时排行榜 ​

需求:

  • 实时更新用户分数
  • 查询前 100 名
  • 查询用户排名

技术选型:

  • Redis Sorted Set
    • ZADD: 添加/更新分数
    • ZREVRANGE: 获取排名前 N
    • ZREVRANK: 获取用户排名

优化:

  • 分段排行榜(按时间、地区)
  • 预计算(定时更新)
  • 缓存热门数据

案例 3:设计分布式限流器 ​

算法选择:

固定窗口: 简单但有突刺问题 滑动窗口: 平滑但实现复杂 令牌桶: 允许突发流量 漏桶: 匀速处理请求

实现: Redis + Lua 脚本保证原子性


8. 实战练习 ​

练习 1:设计 Instagram ​

要求:

  • 用户可以上传照片
  • 用户可以关注其他用户
  • Feed 流显示关注用户的照片
  • 点赞和评论功能

考虑点:

  • 图片存储(CDN)
  • Feed 生成(推模式 vs 拉模式)
  • 数据库设计
  • 缓存策略

练习 2:设计在线聊天系统 ​

要求:

  • 一对一聊天
  • 群组聊天
  • 在线状态
  • 消息持久化

考虑点:

  • WebSocket vs 长轮询
  • 消息队列
  • 未读消息计数
  • 消息存储

练习 3:设计搜索自动完成 ​

要求:

  • 用户输入时实时提示
  • 支持拼音搜索
  • 支持热门搜索

考虑点:

  • Trie 树
  • 缓存策略
  • 实时更新
  • 个性化推荐

9. 延伸阅读 ​

推荐书籍 ​

  • 《系统设计面试:内幕指南》
  • 《设计数据密集型应用》
  • 《大规模分布式存储系统》
  • 《微服务设计》

在线资源 ​

实践平台 ​

  • LeetCode System Design
  • Pramp
  • Exponent

下一章:电商平台项目实战

由 VitePress 构建,Markdown 教材原地维护。