一、系统设计面试概述
系统设计面试是高级工程师和架构师岗位的必考环节。面试官希望通过一道开放性问题,考察候选人的全局思维、技术深度和工程经验。
二、经典面试题及解析
题目1:设计一个短网址服务
需求分析:
- 长URL → 短URL的映射
- 支持高并发访问
- 短URL尽可能短
核心设计:
java
// 基于自增ID + Base62编码
public class ShortUrlService {
private static final String BASE62 =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
public String encode(long id) {
StringBuilder sb = new StringBuilder();
while (id > 0) {
sb.append(BASE62.charAt((int)(id % 62)));
id /= 62;
}
return sb.reverse().toString();
}
// 存储:Redis + MySQL双写
public String shorten(String longUrl) {
long id = idGenerator.nextId();
String shortKey = encode(id);
// 写入Redis缓存
redisTemplate.opsForValue().set(
"short:" + shortKey, longUrl, 7, TimeUnit.DAYS);
// 写入MySQL持久化
urlMapper.insert(new UrlMapping(id, shortKey, longUrl));
return "https://t.cn/" + shortKey;
}
}
题目2:设计一个秒杀系统
核心挑战:
- 瞬时高并发(10万QPS+)
- 防止超卖
- 保证公平性
架构设计:
用户请求 → Nginx限流 → API网关
↓
Redis预扣库存
↓
消息队列异步下单
↓
数据库扣减库存
java
// Redis预扣库存(Lua脚本保证原子性)
public boolean deductStock(String productId, int count) {
String script =
"if (redis.call('exists', KEYS[1]) == 1) then " +
" local stock = tonumber(redis.call('get', KEYS[1])); " +
" if (stock >= tonumber(ARGV[1])) then " +
" redis.call('decrby', KEYS[1], ARGV[1]); " +
" return 1; " +
" end; " +
"end; " +
"return 0;";
Long result = redisTemplate.execute(
new DefaultRedisScript<>(script, Long.class),
Collections.singletonList("stock:" + productId),
String.valueOf(count));
return result != null && result == 1;
}
题目3:设计一个消息系统(类似微信)
核心模块:
- 用户管理
- 消息收发
- 离线消息
- 消息已读/未读
技术选型:
| 模块 | 方案 |
|---|---|
| 长连接 | WebSocket / Netty |
| 消息存储 | MySQL + MongoDB |
| 离线消息 | Redis队列 |
| 群聊 | 消息扇出 |
| 消息同步 | 推拉结合模式 |
java
// 推拉结合模式
// 推:新消息实时推送
// 拉:客户端上线后拉取离线消息
public List pullOfflineMessages(String userId) {
String key = "offline:" + userId;
List messages = redisTemplate.opsForList()
.range(key, 0, -1);
redisTemplate.delete(key);
// 反序列化返回
return messages.stream()
.map(this::deserialize)
.collect(Collectors.toList());
}
题目4:设计一个Feed流系统
三种方案对比:
| 方案 | 优点 | 缺点 |
|---|---|---|
| 推模式(写扩散) | 读快 | 写慢,粉丝多成本高 |
| 拉模式(读扩散) | 写快 | 读慢,大V成本高 |
| 推拉结合 | 平衡 | 实现复杂 |
java
// 推拉结合:普通用户推,大V拉
public List getFeedTimeline(String userId) {
User user = userMapper.selectById(userId);
if (user.isBigV()) {
// 大V:拉取关注的人的最新动态
return feedMapper.pullFromFollowings(userId);
} else {
// 普通用户:从收件箱读取
return redisTemplate.opsForList()
.range("inbox:" + userId, 0, 50);
}
}
三、答题框架
系统设计面试的标准答题流程:
- 理解需求 - 主动提问,明确功能范围
- 高层设计 - 画出整体架构图
- 深入设计 - 选择核心组件详细展开
- 扩展讨论 - 可扩展性、容错、监控
- 总结回顾 - Trade-off取舍说明
四、常见考察点
- 数据一致性:如何保证分布式场景下的数据一致性
- 高可用:单点故障如何处理
- 可扩展:数据量增长10倍怎么办
- 安全性:防攻击、权限控制
- 监控:如何发现和定位问题
五、总结
系统设计面试不是要求完美方案,而是考察:
- ✅ 结构化思维
- ✅ 技术选型的权衡能力
- ✅ 实际工程经验
- ✅ 沟通表达能力
思考题:你遇到过最有趣的系统设计面试题是什么?你是怎么回答的?
个人观点,仅供参考