搞定系统设计 - Alex Xu

系统设计面试被认为是所有技术面试中难度最大的面试。本书重点讨论了分布式系统中的常用组件和大型 Web 应用的系统架构,涵盖了几类常见的典型应用,包括聊天系统、视频流系统、文件存储系统(云盘)、支付系统等。
关于作者
Alex Xu 是系统设计领域的知名技术作家:
- 《System Design Interview》系列作者:该系列已成为系统设计面试的标准参考书
- 前 Twitter 工程师:参与过大规模分布式系统的开发
- 技术博主:其关于系统设计的文章在网络上广为流传
- 面试专家:帮助数千名工程师通过系统设计面试
Alex 以其清晰的结构化方法和直观的图表著称,擅长将复杂的系统设计问题拆解为可理解的组件。
核心内容
1. 系统设计面试框架
系统设计面试四步法:
1. 需求澄清 (Clarify Requirements)
- 功能需求:系统需要实现什么功能?
- 非功能需求:性能、可用性、一致性要求?
- 用户规模:DAU、MAU、峰值 QPS?
2. 高层设计 (High-Level Design)
- 核心组件:客户端、API 网关、服务、数据库
- 数据流:请求如何流动?
- 技术选型:SQL vs NoSQL、缓存策略?
3. 详细设计 (Deep Dive)
- 数据模型:表结构、索引设计
- 核心算法:推荐、排序、分发
- 瓶颈分析:哪里可能成为瓶颈?
4. 扩展讨论 (Scalability Discussion)
- 水平扩展:如何分片?
- 缓存策略:多层缓存设计
- 容错处理:故障转移、降级策略
2. 负载均衡
负载均衡算法:
1. 轮询 (Round Robin)
- 简单,但不考虑服务器负载
- 适合服务器性能相近的场景
2. 加权轮询 (Weighted Round Robin)
- 根据服务器性能分配权重
- 适合异构服务器集群
3. 最少连接 (Least Connections)
- 将请求分发给连接数最少的服务器
- 适合长连接场景
4. 一致性哈希 (Consistent Hashing)
- 减少节点变化时的数据迁移
- 适合缓存集群
负载均衡器:
- 硬件:F5、A10
- 软件:Nginx、HAProxy
- 云服务:AWS ELB/ALB、阿里云 SLB
3. 缓存策略
// 缓存模式
// 1. Cache-Aside (旁路缓存)
function getData(key) {
// 先读缓存
let data = cache.get(key);
if (data === null) {
// 缓存未命中,读数据库
data = db.query(key);
// 写入缓存
cache.set(key, data, TTL);
}
return data;
}
// 2. Read-Through (读穿透)
// 缓存作为主要接口,自动从数据库加载
// 3. Write-Through (写穿透)
function setData(key, value) {
// 同时写缓存和数据库
cache.set(key, value);
db.update(key, value);
}
// 4. Write-Behind (写回)
function setData(key, value) {
// 只写缓存,异步批量写数据库
cache.set(key, value);
asyncQueue.add(() => db.update(key, value));
}
// 缓存失效策略
// 1. TTL (Time To Live)
cache.set(key, value, { ttl: 3600 });
// 2. LRU (Least Recently Used)
// 淘汰最近最少使用的数据
// 3. LFU (Least Frequently Used)
// 淘汰最不常用的数据
4. 数据库分片
分片策略:
1. 基于范围分片 (Range-based Sharding)
- 例如:user_id 1-1000 在 shard1,1001-2000 在 shard2
- 优点:范围查询高效
- 缺点:可能数据分布不均
2. 基于哈希分片 (Hash-based Sharding)
- 例如:shard = hash(user_id) % N
- 优点:数据分布均匀
- 缺点:范围查询困难
3. 基于地理位置分片 (Geo-based Sharding)
- 例如:亚洲用户在 asia-db,欧洲用户在 eu-db
- 优点:就近访问,延迟低
- 缺点:跨区域查询复杂
分片后的挑战:
- 跨分片查询
- 分布式事务
- 动态扩容
- 全局唯一 ID 生成