系统设计面试八股文(20题)
系统设计面试八股文(20 题)
📚 面试高频:本文覆盖系统设计核心知识点,从基础架构到高级设计,帮你系统掌握系统设计面试要点。
🎯 面试加分:每个问题都包含深度解析和面试加分回答,让你在面试中脱颖而出。
⚡ 快速掌握:所有问题都附有通俗易懂的解释和实战经验分享。
📖 学习指南
🎯 学习目标:通过本文,你将系统掌握系统设计的核心概念、设计思路和实战技巧,能够自信地应对任何系统设计相关的面试问题。
适合人群
- 🔰 初学者:想系统学习系统设计的开发者
- 🚀 有经验者:想深入理解系统设计原理的高级开发者
- 💼 面试准备者:想刷系统设计面试题的求职者
学习建议
- 先理解需求,再设计方案:先搞懂”要解决什么问题”,再搞懂”如何设计”
- 结合实战场景:不要死记硬背,要理解实际应用场景
- 动手实践:在自己电脑上搭建本文的示例系统
- 反复复习:面试前一周,每天复习 5 个问题
学习时间估算
- ⏱️ 快速复习(只看一句话总结):1.5 小时
- 📚 系统学习(看深度解析):2 天
- 💪 深入理解(研究源码):1 个月+
🗺️ 知识图谱
mindmap
root((系统设计))
基础架构
负载均衡
CDN
缓存
数据库
消息队列
高级设计
分布式锁
分布式事务
一致性哈希
CAP 定理
实战系统
短链接系统
限流器
唯一 ID 生成
秒杀系统
推荐系统
搜索引擎
聊天系统
视频网站
⚠️ 常见陷阱与误区
陷阱 1:混淆负载均衡算法
❌ 错误理解:
- 以为所有场景都适合轮询算法
✅ 正确认知:
- 轮询算法:适合服务器性能一致的场景
- 加权轮询算法:适合服务器性能不一致的场景
- 最少连接数算法:适合长连接场景
- IP Hash 算法:适合需要会话保持的场景
陷阱 2:忽略缓存穿透、缓存击穿、缓存雪崩
❌ 错误做法:
- 只使用缓存,不考虑缓存问题
✅ 正确做法:
- 缓存穿透:使用布隆过滤器或缓存空值
- 缓存击穿:使用互斥锁或逻辑过期时间
- 缓存雪崩:使用过期时间随机化或集群部署
陷阱 3:混淆 CAP 定理的三个特性
❌ 错误理解:
- 以为 CAP 可以同时保证 C、A、P
✅ 正确认知:
- C(Consistency)一致性:所有节点在同一时间看到相同的数据
- A(Availability)可用性:每个请求都能收到响应(不保证最新数据)
- P(Partition tolerance)分区容错性:系统在网络分区时仍能正常运行
- CAP 定理:分布式系统最多只能同时满足其中两个特性
💡 面试技巧
🎯 面试技巧:面试时遇到系统设计问题,不要只背方案,要结合实际项目经验回答。
回答思路
- 先问清楚需求:功能需求、非功能需求(QPS、延迟、数据量)
- 再给出高层设计:画出系统架构图(负载均衡、缓存、数据库、消息队列)
- 最后深入讨论细节:数据库 schema、缓存策略、消息队列选型
举例说明
问题:如何设计一个短链接系统?
一句话总结:短链接系统的核心是将长链接映射到一个短链接,通过重定向实现访问。
高层设计:
- 功能需求:输入长链接,返回短链接;访问短链接,重定向到长链接
- 非功能需求:高可用、低延迟、可扩展
- 系统架构:负载均衡 → API 服务 → 数据库(存储映射关系) → 缓存(提高读取性能)
面试加分回答:
“在实际项目中,短链接系统需要考虑:
- 唯一 ID 生成:可以使用雪花算法或自增 ID
- 缓存策略:热点短链接放在 Redis 缓存中
- 数据库选型:MySQL(存储映射关系)、Redis(缓存)
- 可扩展性:使用一致性哈希分片数据”
Q1:如何设计一个短链接系统(URL Shortener)?
一句话总结:短链接系统的核心是将长链接映射到一个短链接,通过重定向实现访问,需要解决唯一 ID 生成、映射存储、重定向、高可用等问题。
深度解析:
1. 需求分析:
- 功能需求:
- 输入长链接,返回短链接
- 访问短链接,重定向到长链接
- 非功能需求:
- 高可用(99.999%)
- 低延迟(< 100ms)
- 可扩展(支持亿级短链接)
2. 高层设计:
1 | |
3. 核心问题:
问题 1:如何生成短链接?
- 方案 1:自增 ID + Base62 编码
- 使用自增 ID(MySQL 自增主键或分布式 ID 生成器)
- 将自增 ID 转换成 Base62 编码(0-9、a-z、A-Z,共 62 个字符)
- 示例:自增 ID = 1234567890 → Base62 编码 = “1LPUP” → 短链接 = “https://short.url/1LPUP“
- 方案 2:哈希(MD5、SHA-1)+ Base62 编码
- 对长链接进行哈希,取前 6-8 个字符作为短链接
- 可能存在哈希冲突,需要重试
问题 2:如何存储映射关系?
- 数据库 schema:
1
2
3
4
5
6
7
8CREATE TABLE short_url (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
short_key VARCHAR(10) UNIQUE NOT NULL,
long_url TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP NULL
);
CREATE INDEX idx_short_key ON short_url(short_key); - 缓存策略:
- 热点短链接放在 Redis 缓存中
- 缓存过期时间:24 小时
面试加分回答:
“在实际项目中,短链接系统需要考虑:
- 唯一 ID 生成:推荐使用自增 ID + Base62 编码(简单、高效)
- 缓存策略:热点短链接放在 Redis 缓存中,提高读取性能
- 数据库选型:MySQL(存储映射关系)、Redis(缓存)
- 可扩展性:使用一致性哈希分片数据(如果用户量增长,可以增加数据库分片)”
Q2:如何设计一个限流器(Rate Limiter)?
一句话总结:限流器的核心是控制请求速率,防止系统被突发流量打垮,常见算法有固定窗口、滑动窗口、令牌桶、漏桶。
深度解析:
1. 限流的作用:
- 保护系统:防止系统被突发流量打垮
- 公平使用:防止单个用户占用过多资源
- 成本控制:控制调用次数,降低成本(如第三方 API 调用)
2. 限流算法:
算法 1:固定窗口(Fixed Window)
- 原理:将时间分成固定大小的窗口,每个窗口内最多允许 N 个请求
- 优点:实现简单
- 缺点:无法应对突发流量(如窗口边界处,可能有 2N 个请求)
算法 2:令牌桶(Token Bucket)
- 原理:以固定速率生成令牌,放入桶中;请求到来时,从桶中获取令牌;如果桶中没有令牌,拒绝请求
- 优点:允许突发流量(桶中有令牌时,可以一次性处理多个请求)
- 缺点:实现复杂
3. 限流架构:
- 单机限流:使用内存计数器(如 Guava 的
RateLimiter) - 分布式限流:使用 Redis + Lua 脚本(保证原子性)
面试加分回答:
“在实际项目中,限流器的设计需要考虑:
- 限流算法选择:
- 如果允许突发流量:选择令牌桶算法
- 如果要求流量平滑:选择漏桶算法
- 限流粒度:
- 对用户限流:防止单个用户占用过多资源
- 对 IP 限流:防止恶意攻击
- 分布式限流:使用 Redis + Lua 脚本(保证原子性)”
Q3:如何设计一个分布式唯一 ID 生成系统?
一句话总结:分布式唯一 ID 生成系统需要保证全局唯一、有序、高性能、高可用,常见方案有UUID、数据库自增 ID、雪花算法、Redis、Leaf。
深度解析:
1. 唯一 ID 的要求:
- 全局唯一:ID 不能重复
- 有序:ID 最好有序(方便数据库索引)
- 高性能:生成 ID 的速度要快
- 高可用:生成 ID 的服务不能宕机
2. 唯一 ID 生成方案:
方案 1:UUID
- 原理:128 位,全球唯一
- 优点:实现简单,性能高
- 缺点:
- 无序(不适合作为数据库主键,会导致索引碎片化)
- 长度长(36 个字符,占用存储空间)
- 可读性差
方案 3:雪花算法(Snowflake)
- 原理:64 位 ID,由**时间戳(41 位)+ 机器 ID(10 位)+ 序列号(12 位)**组成
- 优点:
- 有序(时间戳在高位,ID 按时间递增)
- 高性能(每秒可生成 4096 * 2^10 = 419 万个 ID)
- 高可用(不依赖外部服务)
- 缺点:
- 时钟回拨问题(如果系统时钟回拨,可能生成重复 ID)
- 机器 ID 需要手动配置(或使用时服务分配)
面试加分回答:
“在实际项目中,分布式唯一 ID 生成系统的设计需要考虑:
- 有序性要求:如果用作数据库主键,推荐使用雪花算法或 Leaf(有序,避免索引碎片化)
- 性能要求:如果 QPS 很高,推荐使用雪花算法或 Redis
- 可用性要求:如果要求高可用,推荐使用雪花算法或 Leaf”
Q4:如何设计一个秒杀系统?
一句话总结:秒杀系统的核心是限流、削峰、异步处理,防止高并发流量打垮系统。
深度解析:
1. 需求分析:
- 功能需求:
- 用户点击秒杀按钮,下单购买
- 库存扣减(防止超卖)
- 订单创建
- 非功能需求:
- 高并发(10 万 QPS)
- 低延迟(< 100ms)
- 高可用(99.99%)
2. 核心挑战:
- 高并发读:商品详情页 QPS 很高
- 高并发写:下单、支付 QPS 很高
- 库存超卖:多个用户同时下单,库存扣减可能超卖
3. 设计方案:
方案 1:前端限流 + 后端异步
1 | |
方案 2:分层限流 + 多级缓存
1 | |
面试加分回答:
“在实际项目中,秒杀系统的设计要点:
- 前端限流:按钮置灰、验证码、答题(防止脚本刷单)
- 网关限流:Nginx limit_req 模块、Sentinel 网关限流
- Redis 预扣库存:利用 Redis 单线程特性,原子性扣减库存
- MQ 异步下单:削峰填谷,防止数据库被打垮”
—### Q5:如何设计一个分布式锁?
一句话总结:分布式锁的核心是互斥性、可重入、防死锁、高可用,实现方案有 Redis、Zookeeper、etcd。
深度解析:
1. 分布式锁的要求:
- 互斥性:同一时间只有一个客户端能持有锁
- 可重入:同一个客户端可以多次获取同一把锁
- 防死锁:即使持有锁的客户端宕机,锁也能自动释放
- 高可用:锁服务不能成为单点故障
2. 分布式锁实现方案:
方案 1:Redis 实现分布式锁
- 获取锁:
SET lock_key unique_value NX EX 10(NX:不存在才设置,EX:10 秒过期) - 释放锁:使用 Lua 脚本保证原子性
1
2
3
4
5if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
else
return 0
end - 优点:性能高,实现简单
- 缺点:
- 时钟漂移问题(主从切换时可能丢失锁)
- 锁过期时间难以估算(业务执行时间可能超过锁过期时间)
方案 2:Zookeeper 实现分布式锁
- 原理:利用 Zookeeper 的临时顺序节点
- 多个客户端在同一父节点下创建临时顺序节点
- 序号最小的节点获取锁
- 其他客户端监听前一个序号节点
- 持有锁的客户端宕机,临时节点自动删除,下一个客户端获取锁
- 优点:
- 可靠性高(CP 系统,强一致性)
- 自带 Watch 机制,不用轮询
- 缺点:性能不如 Redis
3. 方案对比:
| 方案 | 一致性 | 性能 | 复杂度 | 推荐场景 |
|---|---|---|---|---|
| Redis | 最终一致 | 高 | 低 | 并发高,允许偶尔锁失效 |
| Zookeeper | 强一致 | 中 | 中 | 一致性要求高 |
| etcd | 强一致 | 中高 | 中 | 一致性要求高,K8s 环境 |
面试加分回答:
“在实际项目中,分布式锁的选型:
- 并发高,允许偶尔锁失效:选择 Redis(如秒杀库存扣减)
- 一致性要求高:选择 Zookeeper 或 etcd(如金融转账)
实际面试中,可以深入讲解 Redis 分布式锁的缺陷:
- 时钟漂移:主节点时钟跳变,导致锁提前过期
- 主从切换:主节点加锁成功,还没同步到从节点,主节点宕机,从节点升级为主节点,另一个客户端也能加锁成功(锁失效)”
Q6:如何设计一个消息队列(MQ)?
一句话总结:消息队列的核心是高性能、高可用、不丢消息、顺序性、幂等性。
深度解析:
1. 需求分析:
- 功能需求:
- 生产者发送消息
- 消费者消费消息
- 消息存储
- 消息投递语义(至少一次、至多一次、精确一次)
- 非功能需求:
- 高性能(10 万+ QPS)
- 高可用(99.99%)
- 不丢消息
2. 核心问题:
问题 1:如何保证高性能?
- 顺序写磁盘:消息追加到日志文件(比随机写快)
- 零拷贝:sendfile() 系统调用,减少内核空间和用户空间之间的拷贝
- 批量发送:生产者批量发送消息(减少网络往返)
- 批量消费:消费者批量拉取消息(减少网络往返)
问题 2:如何保证高可用?
- 集群部署:多 Broker 组成集群
- 副本机制:每个分区(Partition)有多个副本(Leader + Follower)
- Leader 故障自动切换:Controller 负责故障转移
面试加分回答:
“在实际项目中,设计一个消息队列需要考虑:
- 存储选型:使用顺序写磁盘 + 零拷贝,提高性能
- 高可用:多 Broker + 多副本 + 自动故障转移
- 不丢消息:生产者 Confirm + Broker 持久化 + 消费者手动提交 Offset
实际面试中,可以举一个订单系统的例子:
- 订单创建后,发送『订单创建』消息到 Kafka
- 库存服务、支付服务、通知服务消费该消息
- 保证不丢消息:生产者开启 Confirm,Broker 使用 3 副本,消费者手动提交 Offset”
Q7:如何设计一个分布式文件系统(如 HDFS、S3)?
一句话总结:分布式文件系统的核心是分块存储、多副本、高可用、高可靠。
深度解析:
1. 需求分析:
- 功能需求:
- 文件上传、下载
- 文件分块存储
- 文件副本管理
- 非功能需求:
- 高可用(99.99%)
- 高可靠(数据不丢失)
- 可扩展(支持 PB 级存储)
2. 系统架构:
1 | |
3. 核心问题:
问题 1:如何分块存储?
- 分块:文件分成固定大小的块(如 128 MB)
- 优点:
- 支持大文件存储
- 方便并行读写
- 方便副本管理
问题 2:如何保证高可靠?
- 多副本:每个块存储 3 个副本(不同机架)
- 副本放置策略:
- 第一个副本:放在客户端所在节点
- 第二个副本:放在不同机架的节点
- 第三个副本:放在与第二个副本相同机架的不同节点
面试加分回答:
“在实际项目中,设计分布式文件系统需要考虑:
- 分块大小选择:128 MB(平衡元数据开销和并行度)
- 副本数量选择:3 副本(可靠性 vs 存储成本)
- 机架感知:副本放在不同机架(防止机架故障)”
Q8:如何设计一个推荐系统?
一句话总结:推荐系统的核心是用户画像、物品画像、推荐算法、实时性。
深度解析:
1. 推荐算法:
算法 1:协同过滤(Collaborative Filtering)
- 基于用户:找到相似用户,推荐相似用户喜欢的物品
- 基于物品:找到相似物品,推荐用户喜欢的物品的相似物品
- 优点:简单,效果好
- 缺点:冷启动问题、数据稀疏问题
算法 2:内容推荐(Content-Based Filtering)
- 原理:根据用户历史行为,推荐相似物品
- 优点:解决冷启动问题
- 缺点:推荐结果单一
2. 系统架构:
1 | |
面试加分回答:
“在实际项目中,推荐系统的设计要点:
- 推荐算法选择:协同过滤(主流)+ 内容推荐(解决冷启动)
- 实时性:离线推荐 + 实时推荐(Flink)
- 排序:推荐结果需要排序(根据点击率、转化率)
实际面试中,可以举一个抖音推荐的例子:
- 用户观看视频的行为(点赞、评论、分享)实时发送到 Kafka
- Flink 实时计算用户画像(喜欢的视频类型、标签)
- 推荐算法根据用画像推荐相似视频
- 推荐结果排序(根据视频的热度、新鲜度)”
Q9:如何设计一个搜索引擎(如 Google、百度)?
一句话总结:搜索引擎的核心是爬取、索引、排序。
深度解析:
1. 系统架构:
1 | |
2. 核心组件:
组件 1:网页爬取(Crawler)
- 原理:从种子 URL 开始,爬取网页,提取链接,继续爬取
- 难点:
- 去重(同一网页多个 URL)
- 反爬(网站禁止爬取)
组件 2:索引构建(Indexer)
- 正排索引:文档 ID → 文档内容
- 倒排索引:单词 → 文档 ID 列表
1
2单词:"Java"
倒排索引:["Java", [文档1, 文档5, 文档10, ...]]
组件 3:排序(Ranking)
- PageRank 算法:根据网页的链接数量和质量排序
- TF-IDF:根据单词在文档中的频率和逆文档频率排序
- 机器学习排序:使用机器学习模型排序(如 BERT)
面试加分回答:
“在实际项目中,搜索引擎的设计要点:
- 倒排索引:核心数据结构,支持快速查询
- 排序算法:PageRank + 机器学习排序
- 索引更新:增量更新(新网页实时加入索引)”
Q10:如何设计一个聊天系统(如微信、WhatsApp)?
一句话总结:聊天系统的核心是实时消息传输、消息存储、消息推送、多端同步。
深度解析:
1. 需求分析:
- 功能需求:
- 一对一聊天
- 群聊
- 消息类型(文本、图片、语音、视频)
- 消息状态(已发送、已送达、已读)
- 非功能需求:
- 低延迟(< 100ms)
- 高可用
- 可扩展(支持亿级用户)
2. 核心问题:
问题 1:如何保证实时消息传输?
- 方案 1:WebSocket(推荐)
- 客户端和服务器建立长连接
- 服务器可以主动推送消息到客户端
- 方案 2:长轮询(Long Polling)
- 客户端发送请求,服务器有消息才返回,否则 Hold 住请求
- 缺点:有延迟
问题 2:如何存储消息?
- 消息存储:
- 关系型数据库(MySQL):存储消息内容
- 时序数据库(InfluxDB):存储消息状态(已发送、已送达、已读)
面试加分回答:
“在实际项目中,聊天系统的设计要点:
- 实时消息传输:使用 WebSocket(低延迟)
- 消息存储:MySQL(消息内容)+ Redis(消息 ID 同步)
- 消息推送:APNs(iOS)、FCM(Android)
- 多端同步:根据消息 ID 拉取消息
实际面试中,可以举一个微信消息同步的例子:
- 用户在手机端发送消息
- 消息同步到 PC 端、iPad 端
- 实现方式:根据消息 ID 拉取消息(每个设备维护自己的消息 ID)”
—### Q11:如何设计一个视频网站(如 YouTube、B站)?
一句话总结:视频网站的核心是视频上传、转码、存储、分发、播放。
深度解析:
1. 需求分析:
- 功能需求:
- 视频上传
- 视频转码(不同清晰度)
- 视频存储
- 视频分发(CDN)
- 视频播放
- 非功能需求:
- 低延迟(< 2s 起播)
- 高可用
- 可扩展(支持亿级视频)
2. 系统架构:
1 | |
3. 核心问题:
问题 1:如何保证视频上传性能?
- 分片上传:大视频分成多个分片,并行上传
- 断点续传:记录已上传的分片,网络中断后继续上传
问题 2:如何转码?
- 转码服务:使用 FFmpeg 转码成多种清晰度(480P、720P、1080P、4K)
- 异步转码:视频上传后,异步转码(消息队列)
面试加分回答:
“在实际项目中,视频网站的设计要点:
- 视频上传:分片上传 + 断点续传
- 视频转码:异步转码(消息队列)+ 多种清晰度
- 视频分发:CDN(就近访问)
- 视频播放:自适应码率(根据网络带宽切换清晰度)”
Q12:如何设计一个分布式缓存系统(如 Redis Cluster)?
一句话总结:分布式缓存系统的核心是数据分片、高可用、一致性哈希。
深度解析:
1. 需求分析:
- 功能需求:
- 数据分片存储
- 高可用(主从复制、故障转移)
- 数据一致性
- 非功能需求:
- 低延迟(< 1ms)
- 高可用(99.99%)
- 可扩展(支持 TB 级数据)
2. 系统架构:
1 | |
3. 核心问题:
问题 1:如何分片数据?
- 一致性哈希:将哈希空间组织成虚拟圆环,数据根据哈希值映射到圆环上
- 优点:增加或删除节点时,只影响相邻节点
- 缺点:数据倾斜(某些节点数据过多)
- 虚拟节点:每个物理节点对应多个虚拟节点,解决数据倾斜问题
面试加分回答:
“在实际项目中,分布式缓存系统的设计要点:
- 数据分片:一致性哈希 + 虚拟节点
- 高可用:主从复制 + 故障转移
- 数据一致性:最终一致性(主节点写,从节点读)”
Q13:如何设计一个 API 网关(如 Kong、Zuul)?
一句话总结:API 网关的核心是路由、负载均衡、限流、认证、监控。
深度解析:
1. 需求分析:
- 功能需求:
- 路由(根据请求路径,转发到后端服务)
- 负载均衡(将请求分发到多个后端服务实例)
- 限流(防止后端服务被突发流量打垮)
- 认证(验证请求是否合法)
- 监控(统计请求量、延迟、错误率)
- 非功能需求:
- 低延迟(< 10ms)
- 高可用
- 可扩展(支持多种协议:HTTP、gRPC、WebSocket)
2. 系统架构:
1 | |
面试加分回答:
“在实际项目中,API 网关的设计要点:
- 路由:根据请求路径转发到后端服务
- 负载均衡:将请求分发到多个后端服务实例
- 限流:令牌桶算法 + Redis
- 认证:JWT 或 OAuth 2.0”
Q14:如何设计一个微服务架构?
一句话总结:微服务架构的核心是服务拆分、服务通信、服务治理、服务监控。
深度解析:
1. 服务拆分:
- 按业务能力拆分:如订单服务、用户服务、商品服务
- 按数据模型拆分:每个微服务有自己的数据库
- 避免过度拆分:服务拆分过细,会增加服务通信成本
2. 服务通信:
- 同步通信:HTTP/REST、gRPC
- 异步通信:消息队列(Kafka、RabbitMQ)
3. 服务治理:
- 配置中心:Apollo、Nacos
- 服务熔断:Hystrix、Sentinel
- 服务降级:返回默认值、返回缓存数据
- 服务限流:Sentinel、Guava RateLimiter
面试加分回答:
“在实际项目中,微服务架构的设计要点:
- 服务拆分:按业务能力拆分,避免过度拆分
- 服务通信:同步用 gRPC(高性能),异步用 Kafka(解耦)
- 服务治理:配置中心 + 熔断 + 降级 + 限流”
Q15:如何设计一个高可用系统?
一句话总结:高可用系统的核心是消除单点故障、故障自动转移、健康检查、监控告警。
深度解析:
1. 消除单点故障:
- 负载均衡:Nginx、HAProxy、云服务商的负载均衡器
- 主从复制:数据库主从复制、Redis 主从复制
- 集群部署:多实例部署(如 Kafka 多 Broker、Elasticsearch 多节点)
2. 故障自动转移:
- 数据库:主库故障,从库自动切换成主库(如 MHA、Orchestrator)
- Redis:主节点故障,从节点自动切换(哨兵模式、Cluster 模式)
面试加分回答:
“在实际项目中,高可用系统的设计要点:
- 消除单点故障:负载均衡 + 主从复制 + 集群部署
- 故障自动转移:数据库主从切换、Redis 哨兵模式
- 健康检查:服务健康检查 + 负载均衡器健康检查
- 监控告警:Prometheus + Grafana 监控,阈值告警”
🗺️ 学习路径总结
🎯 学习路线:从入门到精通,系统掌握系统设计知识的完整学习路径。
📚 第一阶段:入门基础(1-2 周)
目标:掌握系统设计的基础概念和常用模式
学习清单:
- 基础架构:负载均衡、CDN、缓存、数据库
- 常见系统:短链接系统、限流器、唯一 ID 生成系统
- 面试技巧:如何回答系统设计问题
实战项目:设计一个简单的短链接系统
面试重点:Q1(短链接系统)、Q2(限流器)、Q3(唯一 ID 生成)
🚀 第二阶段:进阶实战(2-4 周)
目标:掌握复杂系统的设计方法
学习清单:
- 高并发系统:秒杀系统、分布式锁、消息队列
- 大数据系统:分布式文件系统、推荐系统、搜索引擎
- 实时系统:聊天系统、视频网站
实战项目:设计一个高并发的秒杀系统
面试重点:Q4(秒杀系统)、Q5(分布式锁)、Q6(消息队列)、Q7(分布式文件系统)、Q8(推荐系统)、Q9(搜索引擎)、Q10(聊天系统)
💪 第三阶段:高级精通(1-2 个月)
目标:掌握分布式系统的核心原理和高级设计
学习清单:
- 分布式理论:CAP 定理、一致性哈希、分布式事务
- 分布式系统:分布式缓存、API 网关、微服务架构
- 高可用设计:高可用系统、负载均衡、数据库分库分表
实战项目:设计一个高可用的电商系统
面试重点:Q11(视频网站)、Q12(分布式缓存)、Q13(API 网关)、Q14(微服务架构)、Q15(高可用系统)、Q16(CAP 定理)、Q17(一致性哈希)、Q18(负载均衡)、Q19(数据库分库分表)、Q20(分布式事务)
🏆 第四阶段:架构专家(持续学习)
目标:成为系统设计架构专家,能够设计大规模分布式系统
学习清单:
- 大规模系统:设计支持亿级用户的系统
- 性能优化:QPS 优化、延迟优化、成本控制
- 安全设计:认证、授权、加密、防攻击
- 运维设计:监控、告警、故障恢复、容量规划
实战项目:设计一个支持亿级用户的社交网络
面试重点:系统设计综合能力、架构权衡能力、技术选型能力
📅 学习时间安排
| 阶段 | 时间投入 | 学习目标 | 实战项目 |
|---|---|---|---|
| 第一阶段:入门基础 | 1-2 周,每天 2 小时 | 掌握基础概念和常用模式 | 短链接系统 |
| 第二阶段:进阶实战 | 2-4 周,每天 2-3 小时 | 掌握复杂系统的设计 | 秒杀系统 |
| 第三阶段:高级精通 | 1-2 个月,每天 3-4 小时 | 掌握分布式系统原理 | 电商系统 |
| 第四阶段:架构专家 | 持续学习,每天 1-2 小时 | 成为架构专家 | 社交网络 |
🎯 面试准备建议
1. 基础设计(必须掌握):
- Q1-Q3:短链接系统、限流器、唯一 ID 生成
- Q4-Q6:秒杀系统、分布式锁、消息队列
2. 进阶设计(面试高频):
- Q7-Q10:分布式文件系统、推荐系统、搜索引擎、聊天系统
- Q11-Q13:视频网站、分布式缓存、API 网关
3. 高级设计(加分项):
- Q14-Q17:微服务架构、高可用系统、CAP 定理、一致性哈希
- Q18-Q20:负载均衡、数据库分库分表、分布式事务
4. 面试技巧:
- 先问清楚需求(功能需求、非功能需求)
- 再给出高层设计(画出系统架构图)
- 最后深入讨论细节(数据库 schema、缓存策略、消息队列选型)
📚 学习资源推荐
官方资源:
- System Design Primer(GitHub 星标最高的系统设计教程)
- High Scalability(大规模系统设计案例)
书籍推荐:
- 《系统设计面试指南》(System Design Interview)
- 《大规模系统设计》(Designing Data-Intensive Applications)
实战项目:
社区:
💡 学习建议:
- 不要急于求成:系统设计知识体系庞大,需要循序渐进
- 动手实践:理论结合实践,多画画系统架构图
- 参与社区:在社区中回答问题,加深理解
- 持续学习:分布式系统不断发展,要保持学习状态
Q14: 如何设计分布式配置中心(Apollo/Nacos)?
一句话总结:分布式配置中心的核心是集中管理配置、支持动态刷新、配置历史管理和灰度发布。
深度解析
1. 为什么需要分布式配置中心?
传统配置方式的问题:
- 配置写在本地文件中,修改需要重启服务
- 配置分散在各个服务中,难以统一管理
- 配置没有历史版本,无法回滚
- 配置没有权限控制,任何人都能修改
分布式配置中心的优势:
- ✅ 集中管理:所有配置在一个地方管理
- ✅ 动态刷新:修改配置后,服务自动刷新(无需重启)
- ✅ 历史管理:配置有历史版本,可以回滚
- ✅ 灰度发布:配置可以按环境、按机器灰度发布
- ✅ 权限控制:配置有权限控制,防止误操作
2. 分布式配置中心的核心功能
| 功能 | 说明 |
|---|---|
| 配置管理 | 集中管理所有配置(新增、修改、删除) |
| 配置刷新 | 修改配置后,服务自动刷新(基于长轮询或 WebSocket) |
| 配置历史 | 记录配置的历史版本,支持回滚 |
| 灰度发布 | 配置可以按环境(dev/test/prod)、按机器(IP)灰度发布 |
| 权限控制 | 配置有读写权限控制,防止误操作 |
| 配置监听 | 服务可以监听配置变化,实时刷新 |
3. Apollo 架构设计
1 | |
核心组件:
- Portal:管理界面,供管理员配置
- Admin Service:管理端,处理配置的增删改查
- Config Service:配置服务,供客户端拉取配置
- Client:客户端,定期拉取配置并缓存到本地
4. 配置刷新机制(长轮询)
Apollo 使用**长轮询(Long Polling)**实现配置动态刷新:
1 | |
5. Nacos 架构设计
Nacos 相比 Apollo 更轻量,支持配置管理和服务发现:
1 | |
6. 配置灰度发布
配置灰度发布的场景:
- 场景 1:配置先在一台机器上生效,验证没问题后再全量发布
- 场景 2:配置按环境(dev/test/prod)分开管理
实现方式(Apollo):
- 在 Portal 上配置灰度规则(按 IP、按环境)
- Config Service 根据灰度规则,返回不同的配置
- 客户端根据灰度规则,拉取对应的配置
7. 实战:Spring Boot 集成 Apollo
1 | |
1 | |
1 | |
面试加分回答
实际项目经验:
“在实际项目中,我们使用 Apollo 管理所有微服务的配置:
- 配置集中管理:所有微服务的配置都放在 Apollo 中,不再分散在各个 jar 包中
- 动态刷新:修改配置后,微服务自动刷新(基于长轮询),无需重启
- 灰度发布:配置先在一台机器上生效,验证没问题后再全量发布
- 权限控制:不同环境(dev/test/prod)有不同的权限,防止误操作
对比 Nacos:Nacos 更轻量,支持配置管理和服务发现,适合小型项目;Apollo 功能更完善,适合大型项目。”
面试高频追问:
- Q: Apollo 和 Nacos 的区别?
- A: Apollo 功能更完善(灰度发布、权限控制、配置历史),适合大型项目;Nacos 更轻量,支持配置管理和服务发现,适合小型项目。
- Q: 配置中心挂了怎么办?
- A: 客户端会缓存配置到本地文件,配置中心挂了不影响服务启动。
Q15: 如何设计分布式日志系统(ELK)?
一句话总结:分布式日志系统的核心是日志收集、日志存储、日志搜索和日志分析,常用方案是 ELK(Elasticsearch + Logstash + Kibana)。
深度解析
1. 为什么需要分布式日志系统?
传统日志方式的问题:
- 日志分散在各个服务器上,排查问题需要登录每台服务器
- 日志量大,用
grep搜索很慢 - 日志没有统一格式,难以分析
- 日志没有告警,问题发现不及时
分布式日志系统的优势:
- ✅ 集中管理:所有日志集中在一个地方
- ✅ 快速搜索:基于 Elasticsearch,秒级搜索 TB 级日志
- ✅ 可视化分析:基于 Kibana,可视化展示日志趋势
- ✅ 告警:日志异常时自动告警(基于 ElastAlert)
2. ELK 架构设计
1 | |
核心组件:
- Logstash:日志收集、过滤、转换(重量级,耗资源)
- Filebeat:日志收集(轻量级,替代 Logstash)
- Elasticsearch:日志存储和搜索(分布式搜索引擎)
- Kibana:日志可视化(图表、仪表盘)
3. 日志收集流程
1 | |
Filebeat 配置(轻量级日志收集):
1 | |
Logstash 配置(日志过滤和转换):
1 | |
4. Elasticsearch 存储设计
索引设计:
- 按日期创建索引:
app-logs-2026.06.17(便于删除过期日志) - 分片数:3-5 个分片(根据日志量调整)
- 副本数:1 个副本(保证高可用)
Mapping 设计:
1 | |
5. Kibana 可视化
常用图表:
- 日志量趋势图:按时间显示日志量(发现异常)
- 错误日志占比:ERROR 日志的占比(监控健康度)
- TOP 10 错误:出现最多的错误(优先解决)
- 响应时间分布:P50、P95、P99 响应时间(性能分析)
6. 日志告警(ElastAlert)
1 | |
面试加分回答
实际项目经验:
“在实际项目中,我们使用 ELK 搭建日志系统:
- 日志收集:每个服务用 Filebeat 收集日志,发送到 Logstash
- 日志过滤:Logstash 解析日志中的时间戳、日志级别、服务名称
- 日志存储:Logstash 将日志存储到 Elasticsearch(按日期创建索引)
- 日志可视化:Kibana 展示日志趋势、错误占比、TOP 10 错误
- 日志告警:ElastAlert 监控 ERROR 日志,超过阈值就邮件告警
优化点:
- 日志量太大:只收集 WARN 和 ERROR 日志,INFO 日志不收集
- Elasticsearch 磁盘占用高:设置索引生命周期策略(ILM),自动删除 7 天前的日志”
面试高频追问:
- Q: ELK 和 Loki 的区别?
- A: ELK 功能强大(全文搜索、复杂聚合),但重量级;Loki 轻量级,只索引元数据(不索引日志内容),适合存储大量日志。
- Q: 如何保证日志不丢失?
- A: Filebeat 支持持久化(将日志缓存到磁盘),Logstash 支持持久化队列(防止 Elasticsearch 挂了丢失日志)。
Q16: 如何设计分布式监控告警系统(Prometheus + Grafana)?
一句话总结:分布式监控告警系统的核心是指标采集、指标存储、指标展示和告警,常用方案是 Prometheus + Grafana。
深度解析
1. 为什么需要分布式监控告警系统?
传统监控方式的问题:
- 监控分散在各个系统中,没有统一视图
- 监控数据没有持久化,历史数据丢失
- 没有告警,问题发现不及时
- 没有可视化,难以分析问题趋势
分布式监控告警系统的优势:
- ✅ 统一监控:所有服务的指标集中在一个地方
- ✅ 持久化存储:监控数据持久化(Prometheus TSDB)
- ✅ 告警:指标异常时自动告警(基于 Prometheus Alertmanager)
- ✅ 可视化:指标可视化展示(基于 Grafana)
2. Prometheus 架构设计
1 | |
核心组件:
- Exporter:暴露指标(如
http_requests_total) - Prometheus Server:采集指标、存储指标(TSDB)
- Grafana:指标可视化(图表、仪表盘)
- Alertmanager:告警管理(去重、分组、路由)
3. 指标采集流程
业务应用暴露指标(Spring Boot Actuator):
1 | |
1 | |
访问 http://localhost:8080/actuator/prometheus,可以看到指标:
1 | |
Prometheus 采集指标(prometheus.yml):
1 | |
4. Prometheus 查询语言(PromQL)
常用查询:
1 | |
5. Grafana 可视化
常用仪表盘:
- QPS 趋势图:每秒请求数(发现流量突增)
- 响应时间图:P50、P95、P99 响应时间(性能分析)
- 错误率图:5xx 错误占比(监控健康度)
- JVM 监控:堆内存、GC 次数、线程数(JVM 调优)
6. 告警规则(Prometheus Alertmanager)
1 | |
1 | |
Alertmanager 配置(告警路由):
1 | |
面试加分回答
实际项目经验:
“在实际项目中,我们使用 Prometheus + Grafana 搭建监控告警系统:
- 指标采集:每个服务暴露 Prometheus 指标(基于 Spring Boot Actuator)
- 指标存储:Prometheus 每 15 秒采集一次指标,存储到 TSDB
- 指标展示:Grafana 展示 QPS、响应时间、错误率、JVM 监控
- 告警:Prometheus Alertmanager 监控错误率、QPS、JVM 内存,超过阈值就邮件告警
优化点:
- Prometheus 存储压力大:使用 Thanos 或 VictoriaMetrics 实现长期存储
- 告警太多:优化告警规则,减少误报(增加
for: 5m持续 5 分钟才告警)”
面试高频追问:
- Q: Prometheus 和 Zabbix 的区别?
- A: Prometheus 适合云原生场景(Kubernetes),基于 Pull 模型;Zabbix 适合传统场景(物理机),基于 Push 模型。
- Q: 如何保证告警不丢失?
- A: Alertmanager 支持高可用部署(集群模式),Prometheus 支持联邦集群(分层采集)。
Q17: 如何设计高并发系统?
一句话总结:高并发系统的设计核心是缓存、异步、分流、限流、降级,通过多层防护保证系统稳定。
深度解析
1. 高并发系统的挑战
| 挑战 | 说明 | 解决方案 |
|---|---|---|
| 海量请求 | QPS 从 1k 飙升到 100k | 负载均衡、分布式部署 |
| 数据库压力 | 大量读请求打垮数据库 | 缓存、读写分离、分库分表 |
| 服务雪崩 | 一个服务挂了,导致整个系统雪崩 | 熔断、降级、限流 |
| 网络带宽 | 大量请求占用带宽 | CDN、压缩、限流 |
2. 高并发系统的设计原则
1 | |
3. 高并发系统的架构设计
1 | |
4. 缓存设计
缓存层次:
- 本地缓存(一级缓存):HashMap、Guava Cache、Caffeine(纳秒级)
- 分布式缓存(二级缓存):Redis、Memcached(毫秒级)
- 数据库(三级缓存):MySQL、PostgreSQL(毫秒级)
缓存策略:
- Cache-Aside(旁路缓存):优先读缓存,缓存没有则读数据库
- Read-Through(读穿透):缓存层负责读数据库
- Write-Through(写穿透):缓存层负责写数据库
缓存问题:
- 缓存穿透:查询不存在的数据(解决方案:布隆过滤器、缓存空值)
- 缓存击穿:热点 Key 过期(解决方案:互斥锁、逻辑过期时间)
- 缓存雪崩:大量 Key 同时过期(解决方案:过期时间随机化、集群部署)
5. 异步处理(消息队列)
适用场景:
- 下单后发送邮件(不需要实时)
- 下单后扣减库存(不需要实时)
- 下单后生成账单(不需要实时)
消息队列选型:
- RabbitMQ:功能丰富(延迟队列、死信队列),适合复杂场景
- Kafka:高吞吐量(百万级 QPS),适合日志、埋点
- RocketMQ:高可靠(金融级),适合电商、金融
6. 限流算法
| 算法 | 说明 | 优点 | 缺点 |
|---|---|---|---|
| 固定窗口 | 统计固定时间内的请求数 | 简单 | 临界问题(两个窗口交界处可能允许 2 倍流量) |
| 滑动窗口 | 统计滑动时间内的请求数 | 精确 | 内存占用高 |
| 漏桶算法 | 请求以固定速率处理 | 流量平滑 | 不能应对突发流量 |
| 令牌桶算法 | 令牌桶中以固定速率生成令牌 | 允许突发流量 | 实现复杂 |
Guava RateLimiter(令牌桶):
1 | |
7. 服务降级和熔断
降级:服务不可用时,返回默认值(如返回缓存数据、返回空数据)
熔断:服务错误率超过阈值时,直接拒绝请求(防止服务雪崩)
Hystrix 熔断规则:
- 请求数达到阈值(如 20 个请求)
- 错误率达到阈值(如 50%)
- 触发熔断(后续请求直接失败,不调用服务)
- 熔断一段时间后,尝试恢复(半开状态)
面试加分回答
实际项目经验:
“在实际项目中,我们设计高并发系统的经验:
- 缓存优先:热点数据放在 Redis 缓存中,缓存没有才读数据库
- 异步处理:下单后,发送邮件、扣减库存、生成账单都异步处理(基于 RocketMQ)
- 限流:API Gateway 使用令牌桶算法限流(1000 QPS)
- 熔断降级:订单服务不可用时,返回缓存的订单数据(基于 Hystrix)
- 无状态设计:所有服务都是无状态的,便于水平扩展
效果:系统支持的 QPS 从 1k 提升到 100k,数据库压力降低了 90%。”
面试高频追问:
- Q: 如何预估系统需要支持多少 QPS?
- A: 根据业务场景预估(如日活用户 100 万,每人平均请求 10 次,集中在 4 小时,则 QPS = 100 万 * 10 / (4 * 3600) ≈ 700 QPS)。
- Q: 缓存和数据库一致性如何保证?
- A: 先更新数据库,再删除缓存(Cache-Aside 策略);或者使用消息队列异步更新缓存。
Q18: 如何设计秒杀系统?
一句话总结:秒杀系统的核心是流量分层过滤、异步处理、流量削峰,保证系统不被瞬时流量打垮。
深度解析
1. 秒杀系统的挑战
| 挑战 | 说明 | 解决方案 |
|---|---|---|
| 瞬时流量高 | 100 万人抢 100 件商品 | 流量分层过滤、限流 |
| 库存超卖 | 100 件商品被 200 人抢到 | 分布式锁、Redis 原子操作 |
| 数据库压力 | 大量下单请求打垮数据库 | 异步处理、消息队列 |
| 恶意刷单 | 黄牛用脚本刷单 | 验证码、风控系统 |
2. 秒杀系统的架构设计
1 | |
3. 流量分层过滤
第 1 层:CDN 过滤静态资源
- 秒杀页面中的图片、CSS、JS 都放在 CDN 上
- 用户请求 CDN,不打到后端服务器
第 2 层:Nginx 限流
- 限制每个 IP 的请求频率(如每个 IP 每秒只能请求 1 次)
- 黑名单:封禁恶意 IP
第 3 层:API Gateway 鉴权和限流
- 鉴权:校验用户是否登录
- 限流:限制每个用户的请求频率(如每个用户每秒只能请求 1 次)
第 4 层:秒杀服务校验库存
- 校验库存是否充足(基于 Redis)
- 校验用户是否已经抢过(基于 Redis Set)
第 5 层:消息队列异步下单
- 下单请求放入消息队列,异步处理
- 数据库批量插入订单(减少数据库连接)
4. 库存预扣减(Redis 原子操作)
问题:100 万人抢 100 件商品,如何防止超卖?
解决方案:使用 Redis 的 DECR 原子操作预扣减库存
1 | |
5. 异步下单(消息队列)
问题:100 万下单请求同时打到数据库,数据库会挂!
解决方案:下单请求放入消息队列,异步处理
1 | |
6. 防刷单(风控系统)
验证码:
- 秒杀前需要输入验证码(防止脚本刷单)
风控系统:
- 检测异常用户(如同一 IP 注册 100 个账号)
- 检测异常订单(如同一用户下单 100 次)
面试加分回答
实际项目经验:
“在实际项目中,我们设计秒杀系统的经验:
- 流量分层过滤:CDN → Nginx 限流 → API Gateway 鉴权限流 → 秒杀服务校验库存
- 库存预扣减:使用 Redis 的
DECR原子操作预扣减库存,防止超卖- 异步下单:下单请求放入 Kafka,异步处理(数据库批量插入订单)
- 防刷单:验证码 + 风控系统(检测异常用户和异常订单)
效果:100 万人抢 100 件商品,系统平稳运行,没有超卖,数据库压力降低了 99%。”
面试高频追问:
- Q: 如果 Redis 挂了怎么办?
- A: Redis 集群部署(主从 + 哨兵),主节点挂了自动切换到从节点。
- Q: 如何防止库存扣减成功但下单失败?
- A: 使用分布式事务(如 Seata),保证库存扣减和下单要么同时成功,要么同时失败。
Q19: 如何设计分布式文件存储系统(FastDFS、MinIO)?
一句话总结:分布式文件存储系统的核心是文件分块、元数据管理、副本机制,保证文件高可用和高可靠。
深度解析
1. 为什么需要分布式文件存储系统?
传统文件存储方式的问题:
- 文件存储在单机磁盘上,磁盘满了无法扩展
- 文件没有备份,磁盘损坏文件丢失
- 文件访问量大时,单机带宽不够
分布式文件存储系统的优势:
- ✅ 水平扩展:文件分散存储在多台服务器上,容量不够就加机器
- ✅ 高可用:文件有多个副本,一台服务器挂了不影响访问
- ✅ 高性能:文件分散在多台服务器上,带宽聚合
2. FastDFS 架构设计
1 | |
核心组件:
- Tracker Server:跟踪服务器,管理 Storage Server(类似注册中心)
- Storage Server:存储服务器,存储文件和文件元数据
- Group:组,一组 Storage Server 互为主从(文件副本)
3. FastDFS 文件上传流程
1 | |
文件 ID 示例:
1 | |
4. MinIO 架构设计
MinIO 是对象存储(类似 AWS S3),适合存储海量小文件(图片、视频、文档)。
1 | |
核心特性:
- 纠删码(Erasure Code):将文件分成 N 个数据块和 M 个校验块,允许最多 M 个块损坏
- Bitrot 保护:自动检测数据损坏(基于哈希校验)
- S3 兼容:API 兼容 AWS S3
5. 实战:Spring Boot 集成 MinIO
1 | |
1 | |
面试加分回答
实际项目经验:
“在实际项目中,我们使用 MinIO 存储用户上传的文件(头像、文档、视频):
- 文件上传:前端上传文件到后端,后端转发到 MinIO
- 文件访问:MinIO 生成文件 URL,返回给前端
- 文件备份:MinIO 使用纠删码(Erasure Code),允许最多 4 个节点挂掉
- 文件权限:MinIO 支持预签名 URL(过期时间 1 小时),防止文件被盗链
对比 FastDFS:FastDFS 适合小文件存储(< 1MB),MinIO 适合任意大小文件存储(兼容 S3 API)。”
面试高频追问:
- Q: 如何保证文件不丢失?
- A: FastDFS 有多副本(同组 Storage Server 互为主从);MinIO 有纠删码(允许最多 M 个块损坏)。
- Q: 如何防止文件被盗链?
- A: MinIO 支持预签名 URL(过期时间 1 小时),只有合法用户才能访问文件。
Q20: 面试实战:如何回答系统设计问题?
一句话总结:回答系统设计问题的核心是先问清楚需求,再给出高层设计,最后深入讨论细节。
深度解析
1. 系统设计问题的回答框架
1 | |
2. 实战:设计一个短链接系统
第 1 步:澄清需求
面试官:设计一个短链接系统。
你:好的,我先澄清一下需求:
- 功能需求:
- 输入长链接,返回短链接
- 访问短链接,重定向到长链接
- 短链接有有效期(可选)
- 非功能需求:
- QPS:100k(读多写少)
- 延迟:< 100ms
- 数据量:1 亿条短链接
- 一致性:最终一致性(短链接生成后可以容忍 1 秒的延迟)
- 约束条件:
- 开发成本:小团队(3 人)
- 运维成本:尽量简单(用托管服务)
- 技术栈:Java + Spring Boot
第 2 步:高层设计
你:我画一下系统架构图(边画边解释):
1 | |
你:系统架构说明:
- 负载均衡:Nginx 或云负载均衡器(分流请求)
- API Service:生成短链接、重定向短链接
- Redis:缓存热点短链接(提高读取性能)
- MySQL:存储长链接和短链接的映射关系
第 3 步:深入讨论细节
面试官:短链接如何生成?
你:短链接生成有两种方案:
方案 1:自增 ID + Base62 编码
- 使用分布式 ID 生成器(如雪花算法)生成自增 ID
- 将 ID 转换为 Base62 编码(0-9、a-z、A-Z,共 62 个字符)
- 优点:短链接长度固定(如 ID=1000,Base62 编码为
G8) - 缺点:需要分布式 ID 生成器
方案 2:长链接 Hash + 碰撞检测
- 对长链接进行 Hash(如 MD5),取前 6 个字符作为短链接
- 如果短链接已存在(碰撞),在长链接后面加随机字符串,重新 Hash
- 优点:不需要分布式 ID 生成器
- 缺点:短链接长度不固定,有碰撞概率
我选择方案 1(分布式 ID 生成器 + Base62 编码)。
面试官:数据库如何设计?
你:
1 | |
面试官:如何保证高并发读取?
你:
- 缓存优先:访问短链接时,先查 Redis 缓存,缓存没有才查数据库
- 缓存预热:热点短链接在系统启动时提前加载到 Redis
- 缓存过期:短链接缓存过期时间设置为 24 小时
第 4 步:扩展讨论
面试官:如果 QPS 从 100k 涨到 1M,怎么办?
你:
- 加缓存:Redis 集群部署(主从 + 分片)
- 加机器:API Service 水平扩展(无状态设计)
- 数据库读写分离:写主库,读从库
- 分库分表:按
short_key进行一致性哈希分片
面试官:如何保证高可用?
你:
- API Service 高可用:多实例部署 + 负载均衡
- Redis 高可用:主从 + 哨兵
- MySQL 高可用:主从切换(MHA 或 Orchestrator)
面试加分回答
实际面试经验:
“在实际面试中,回答系统设计问题的经验:
- 先问清楚需求:不要急于给出方案,先问清楚功能需求和非功能需求
- 画图辅助解释:边画架构图边解释,让面试官更容易理解
- 权衡方案:不要只给一个方案,要给出多个方案并说明优缺点(如短链接生成的两种方案)
- 深入细节:不要只停留在高层设计,要深入讨论数据库 Schema、缓存策略、消息队列选型
- 扩展讨论:主动讨论如何支持更高的 QPS、如何保证高可用
技巧:如果某个技术点不熟悉(如一致性哈希),可以主动说’这个我不太熟悉,但我的理解是…’,不要装懂。”
面试高频追问:
- Q: 如果面试官追问一个你不会的技术点,怎么办?
- A: 不要装懂,可以说’这个我不太熟悉,但我的理解是…’,或者’这个我可以回去研究一下’。面试官更看重你的思考过程,而不是你知道多少。
- Q: 系统设计问题有没有标准答案?
- A: 没有标准答案,面试官更看重你的思考过程(如何分析问题、如何权衡方案、如何深入细节)。
🎉 总结
本文详细讲解了 20 个系统设计核心知识点,从基础架构(负载均衡、缓存、消息队列)到高级设计(短链接、秒杀、分布式锁),再到实战技巧(如何回答系统设计问题)。
核心要点回顾:
- 负载均衡:分层负载均衡(硬件 LB → 软件 LB → 应用 LB)
- 缓存:缓存穿透/击穿/雪崩的解决方案
- 消息队列:RabbitMQ、Kafka、RocketMQ 的选型
- 短链接系统:分布式 ID 生成器 + Base62 编码
- 限流器:令牌桶算法(允许突发流量)
- 唯一 ID 生成:雪花算法(趋势递增、不依赖数据库)
- 秒杀系统:流量分层过滤、库存预扣减、异步下单
- 分布式锁:Redis
SETNX+ 过期时间 + Redlock - 分布式事务:2PC、3PC、TCC、Saga 的优缺点
- 高并发系统:缓存优先、异步处理、限流降级
下一步学习建议:
- 如果你对基础架构还不熟悉,先回头把负载均衡、缓存、消息队列搞清楚
- 如果你对高级设计感兴趣,可以深入研究分布式锁、分布式事务、一致性哈希
- 如果你准备面试,重点看 Q20(如何回答系统设计问题)
📚 扩展学习资源
官方文档
书籍推荐
- 📚 《设计数据密集型应用》(DDIA)
- 📚 《System Design Interview》(Alex Xu)
- 📚 《高性能网站建设指南》
博客推荐
🎉 恭喜你!学完本文后,你已经掌握了系统设计的 进阶知识。
下一步建议:
- 实战练习:自己设计一个聊天系统或视频网站架构
- 深入研究:选一个方向(如分布式事务、一致性哈希)深入研究
- 关注社区:订阅 AWS、Google SRE 博客,学习大厂架构经验
- 准备面试:刷 LeetCode 数据库题 + 系统设计题