系统设计面试指南

June 24, 2026 · View on GitHub

系统设计面试的综合参考,涵盖核心概念、模式和常见问题。

目录


可扩展性基础

可扩展性是系统通过增加资源来处理更大负载的能力。

垂直扩展 vs 水平扩展

方面垂直扩展水平扩展
方法给单台机器增加 CPU/RAM增加更多机器
限制硬件上限实际上无限
成本每单位指数增长每单位线性增长
复杂度简单需要分布式逻辑
停机时间通常需要可实现零停机
单点故障

关键原则

  1. 无状态 - 保持应用服务器无状态,使任何请求可以到达任何服务器。
  2. 松耦合 - 服务应通过明确定义的接口通信。
  3. 冗余 - 在每一层消除单点故障。
  4. 异步处理 - 将长时间运行的任务卸载到后台工作进程。

按层扩展

扩展策略
ClientCDN、浏览器缓存、压缩
Web tier负载均衡器 + 无状态应用服务器
Application tier水平扩展、微服务
Database读副本、分片、缓存
Storage分布式文件系统、对象存储

负载均衡

负载均衡器将传入流量分配到多台服务器。

负载均衡算法

算法描述最适合
Round Robin按顺序分配请求均匀服务器
Weighted Round Robin按权重比例分配混合容量服务器
Least Connections路由到活跃连接最少的服务器变化请求时长
IP Hash基于客户端 IP 路由会话亲和
Least Response Time路由到响应最快的服务器延迟敏感应用
Random随机选择服务器简单无状态设置

负载均衡器类型

  • Layer 4 (传输层) - 基于 IP 和端口路由。快速,无内容检查。示例:AWS NLB、HAProxy (TCP 模式)。
  • Layer 7 (应用层) - 基于 HTTP 头、URL 路径、Cookie 路由。更灵活。示例:AWS ALB、Nginx、Envoy。

健康检查

负载均衡器定期检查服务器健康状况。不健康的服务器从池中移除。

检查类型方法间隔
ActiveLB 发送探测请求每 5-30 秒
PassiveLB 监控真实流量错误持续
Deep检查下游依赖每 30-60 秒

缓存策略

缓存将频繁访问的数据存储在更靠近消费者的位置,以减少延迟和后端负载。

缓存拓扑

拓扑描述优点缺点
Local cache进程内内存最快,无网络大小有限,不共享
Distributed cache独立集群(Redis, Memcached)共享,可扩展网络开销
CDN cache全球边缘位置靠近用户仅静态内容

缓存模式

模式工作原理使用场景
Cache-Aside应用先检查缓存,未命中时从 DB 加载通用
Write-Through同时写入缓存和 DB一致性关键
Write-Behind写入缓存,异步刷新到 DB写入密集
Read-Through缓存未命中时自动从 DB 加载简化应用逻辑
Refresh-Ahead在过期前主动刷新可预测的访问模式

缓存淘汰策略

策略描述
LRU最近最少使用 - 淘汰最早访问的项
LFU最不常用 - 淘汰最不受欢迎的项
FIFO先进先出 - 淘汰最早的项
TTL生存时间 - 固定时长后淘汰

缓存失效挑战

  • 惊群效应 - 缓存未命中时大量请求同时到达 DB。解决方案:锁定或提前重算。
  • 缓存踩踏 - 热门 Key 过期导致 DB 过载。解决方案:概率性过期。
  • 过时数据 - 缓存持有过期值。解决方案:短 TTL 或事件驱动失效。

数据库类型

关系型数据库 (RDBMS)

具有 ACID 事务的结构化数据。示例:PostgreSQL、MySQL、Oracle。

功能描述
Schema固定的预定义结构
Query languageSQL
Transactions完全 ACID 支持
Scaling垂直为主,读副本用于水平
Best for结构化数据、复杂查询、关系

NoSQL 数据库

类型示例最适合数据模型
Key-ValueRedis, DynamoDB缓存、会话存储Key 映射到 Value
DocumentMongoDB, CouchDB灵活 Schema、内容类 JSON 文档
Column-FamilyCassandra, HBase时间序列、高写入吞吐按行分组的列
GraphNeo4j, Amazon Neptune关系、推荐节点和边

数据库扩展

策略描述权衡
Read replicas将数据复制到多个只读实例最终一致性
Sharding将数据拆分到多个数据库跨分片复杂查询
Federation按功能拆分(用户 DB、产品 DB)跨功能查询
Denormalization复制数据以减少 JOIN数据一致性开销
SQL tuning索引、查询优化收益递减

消息队列

消息队列实现服务间的异步通信。

关键概念

概念描述
Producer向队列发送消息
Consumer读取和处理消息
Queue存储消息的缓冲区
Topic发布/订阅消息的命名通道
Acknowledgment消费者确认成功处理

常见消息队列系统

系统类型优势
Apache Kafka分布式日志高吞吐、可重放、持久
RabbitMQ传统代理灵活路由、成熟
Amazon SQS托管队列完全托管、简单
Redis Streams轻量流低延迟、简单设置

何时使用消息队列

  • 解耦 - 服务无直接依赖通信。
  • 缓冲 - 平滑流量峰值。
  • 异步处理 - 卸载慢操作(邮件发送、图片处理)。
  • 扇出 - 将同一消息传递给多个消费者。
  • 排序 - 保证处理顺序(Kafka 分区)。

投递保证

保证描述实现
At-most-once消息投递零次或一次发送即忘
At-least-once消息投递一次或多次带确认的重试
Exactly-once消息恰好投递一次幂等消费者 + 事务

微服务

一种应用由小型、独立可部署服务组成的架构。

单体 vs 微服务

方面单体微服务
Deployment单一单元每服务独立
Scaling扩展所有按服务扩展
Technology单一栈可多语言
Complexity初期简单规模化时复杂
Team structure共享代码库服务所有权
Failure isolation级联故障隔离故障

通信模式

模式协议使用场景
SynchronousHTTP/REST, gRPC实时请求/响应
Asynchronous消息队列、事件发送即忘、事件驱动
Service meshEnvoy, Istio横切关注点(mTLS、可观测性)

关键挑战

  1. 服务发现 - 服务如何找到彼此。工具:Consul、etcd、Kubernetes DNS。
  2. 分布式事务 - 多服务操作的 Saga 模式。
  3. 可观测性 - 分布式追踪(Jaeger)、集中日志(ELK)、指标(Prometheus)。
  4. 数据一致性 - 通过事件源或 Outbox 模式实现最终一致性。
  5. 配置管理 - 集中配置服务器或基于环境的配置。

CAP 定理

分布式系统最多只能保证三个属性中的两个。

三个属性

属性含义
Consistency每次读取都收到最近的写入
Availability每个请求都收到响应
Partition Tolerance系统在网络分区时继续运行

常见组合

选择权衡示例
CP牺牲可用性换取一致性HBase, MongoDB(强一致性模式)
AP牺牲一致性换取可用性Cassandra, DynamoDB
CA在分布式系统中不现实单节点数据库

PACELC 扩展

如果分区 (P):在可用性 (A) 和一致性 (C) 之间选择。 否则 (E):在延迟 (L) 和一致性 (C) 之间选择。

系统分区正常
CassandraAPEL
MongoDBCPEC
DynamoDBAPEL

一致性哈希

一种在集群中分配数据的技术,当节点变化时重新分配最小化。

工作原理

  1. 将服务器和 Key 映射到哈希环(0 到 2322^{32} - 1)。
  2. 每个 Key 分配到环上顺时针方向的下一个服务器。
  3. 当服务器添加或移除时,仅相邻 Key 被重新映射。

虚拟节点

为避免不均匀分布,每台物理服务器在环上获得多个虚拟位置。

物理服务器虚拟节点分布方差
3每台 1 个
3每台 100 个
3每台 200 个非常低

优势

优势描述
最小重分配节点变化时平均仅移动 K/n 个 Key
可扩展性易于添加/移除节点
负载均衡虚拟节点确保均匀分布

使用场景

  • 分布式缓存(Memcached, Redis Cluster)
  • 数据库分片
  • CDN 边缘服务器路由
  • 分布式哈希表

速率限制

控制客户端在时间窗口内可以发出的请求数量。

算法

算法描述优点缺点
Token Bucket以固定速率添加 Token,每次请求消耗允许突发突发流量
Leaky Bucket以固定速率处理请求平滑输出无突发容忍
Fixed Window在固定时间窗口计数请求简单边界突发问题
Sliding Window Log记录时间戳,在滚动窗口内计数准确内存密集
Sliding Window Counter当前和前一窗口的加权计数准确、高效轻微近似

速率限制响应

HTTP Code含义使用时机
429Too Many Requests客户端超出限制
Retry-After header距下次允许请求的秒数告知客户端等待时间

分布式速率限制

方法描述权衡
Centralized counter (Redis)单一事实来源单点故障
Local + sync每节点本地跟踪,定期同步轻微不准确
Sticky sessions将客户端路由到同一节点减少可用性

速率限制头

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1623456789

CDN

内容分发网络在全球边缘位置缓存内容以减少延迟。

CDN 工作原理

  1. 用户从源服务器请求内容。
  2. DNS 解析到最近的边缘服务器。
  3. 边缘服务器检查其缓存。
  4. 缓存命中时,直接提供内容。
  5. 缓存未命中时,边缘从源获取,缓存后提供。

CDN 类型

类型描述使用场景
Push CDN您上传内容到 CDN大文件、不频繁更新
Pull CDN首次请求时 CDN 从源获取动态内容、简单设置

CDN 缓存策略

策略描述
Cache-Control headersmax-age, s-maxage, no-cache 指令
Versioned URLs/app.v2.js 在部署时强制缓存刷新
Purge手动失效缓存内容
Stale-while-revalidate提供旧内容,后台刷新

优势

优势影响
减少延迟从最近的边缘提供内容
减少源负载大多数请求在边缘处理
DDoS 保护流量分布在边缘
高可用冗余边缘服务器

API 设计

REST API 最佳实践

实践示例
使用名词作为资源GET /users 而非 GET/getUsers
HTTP 方法映射到 CRUDGET=读取, POST=创建, PUT=更新, DELETE=删除
版本化 API/api/v1/users
一致命名/users/{id}/posts 用于嵌套资源
分页?page=2&limit=20
筛选?status=active&sort=created_at

HTTP 状态码

Code含义使用时机
200OK成功读取/更新
201Created成功创建资源
204No Content成功删除
400Bad Request无效输入
401Unauthorized需要认证
403Forbidden权限不足
404Not Found资源不存在
409Conflict重复或冲突状态
429Too Many Requests超出速率限制
500Internal Server Error意外服务器故障

API 风格对比

风格协议格式最适合
RESTHTTPJSONCRUD、Web API
GraphQLHTTPJSON复杂查询、移动端
gRPCHTTP/2Protobuf微服务、低延迟
WebSocketWSAny实时、双向

错误响应格式

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Email is required",
    "details": [
      { "field": "email", "issue": "missing required field" }
    ]
  }
}

常见系统设计问题

URL 短链接

需求:给定长 URL,生成短 URL。将短 URL 重定向到原始 URL。

组件选择原因
Key 生成自增 ID 的 Base62 编码短、唯一、确定性
DatabaseKey-Value 存储(DynamoDB)按短码简单查找
CacheRedis热门 URL 缓存以快速重定向
Encoding哈希前 7 个字符62762^{7} = ~3.5 万亿唯一 URL

请求流程

  1. 客户端发送长 URL 到 API 服务器。
  2. 服务器生成唯一短码(基于哈希或 ID)。
  3. 存储映射到数据库。
  4. 返回短 URL。

读取流程

  1. 用户访问短 URL。
  2. 在缓存中查找短码,然后 DB。
  3. 返回 301 重定向到原始 URL。

容量估算(示例):

  • 每月 1 亿 URL,10:1 读写比
  • 存储:1 亿 * 500 字节 = 每月 50 GB
  • 读取 QPS:~400 次/秒

聊天系统

需求:支持一对一和群组消息,带送达回执。

组件技术用途
ProtocolWebSocket持久双向连接
Message storeCassandra写入密集、时间有序数据
User sessionsRedis跟踪在线状态
Message queueKafka可靠消息投递
NotificationPush service (APNs/FCM)离线用户通知

关键设计决策

决策选择权衡
Message ordering每对话序列号需要协调
Group chat写入时扇出写放大,读简单
Delivery tracking每接收者状态存储开销
Message persistence追加日志快写,不可变历史

连接管理

  • 每个用户维护与聊天服务器的 WebSocket 连接。
  • 连接状态存储在 Redis(user -> server 映射)。
  • 当用户 A 发送给用户 B 时,在 Redis 中查找 B 的服务器,转发消息。

新闻推送

需求:显示来自关注用户的帖子的个性化推送。

组件技术用途
Post storageMySQL/PostgreSQL结构化帖子数据
Feed generationRedis sorted sets每用户预计算推送
Fan-out serviceAsync workers将帖子分发给关注者
Ranking serviceML model个性化排序
CDNCloudFront/Cloudflare媒体内容分发

两种方法

方法工作原理优点缺点
Fan-out on write推送到所有关注者的推送快读名人用户慢
Fan-out on read按需计算推送无写放大慢读
Hybrid普通用户写,名人读均衡实现复杂

推送生成管道

  1. 用户发布帖子。
  2. 帖子存储在数据库。
  3. Fan-out 服务入队投递任务。
  4. 工作进程将帖子 ID 推送到每个关注者的推送(Redis sorted set)。
  5. 当关注者打开应用时,获取预计算的推送。
  6. Ranking service 按相关性重新排序。

关键优化

  • 限制每用户推送存储为最近 N 个帖子。
  • 对大型推送使用候选生成 + 排名。
  • 激进缓存热门推送。
  • 仅为活跃用户预计算推送。

面试技巧

阶段操作时间
Requirements澄清功能和非功能需求5 分钟
Estimation计算 QPS、存储、带宽5 分钟
High-level design画出主要组件和数据流10 分钟
Deep dive详细设计关键组件15 分钟
Tradeoffs讨论替代方案并证明选择5 分钟

要问的问题

  • 预期规模是多少?(用户、QPS、数据量)
  • 延迟要求是什么?
  • 一致性还是可用性更重要?
  • 读写比是多少?
  • 有什么具体约束(成本、技术)?