系统设计题
# 系统设计题
# 🏗️ 系统设计基础
# 1. 设计原则
Q: 系统设计的基本原则有哪些?
A:
- 可扩展性(Scalability):系统能够处理增长的负载
- 可靠性(Reliability):系统在故障时仍能正常工作
- 可用性(Availability):系统保持运行的时间百分比
- 一致性(Consistency):所有节点看到相同的数据
- 分区容错性(Partition Tolerance):系统在网络分区时仍能工作
# 2. CAP定理
Q: 解释CAP定理及其在分布式系统中的应用
A: CAP定理指出分布式系统不能同时满足以下三个特性:
- 一致性(Consistency):所有节点同时看到相同数据
- 可用性(Availability):系统保持可操作
- 分区容错性(Partition Tolerance):系统在网络故障时继续工作
实际应用:
- CP系统:MongoDB、HBase(牺牲可用性保证一致性)
- AP系统:Cassandra、DynamoDB(牺牲一致性保证可用性)
- CA系统:传统RDBMS(在分布式环境下不现实)
# 🎯 经典系统设计题
# 1. 设计短链接服务(如TinyURL)
需求分析:
- 将长URL转换为短URL
- 短URL重定向到原始URL
- 支持自定义短链接
- 统计点击次数
系统架构:
[客户端] → [负载均衡器] → [Web服务器] → [缓存] → [数据库] ↓ [URL编码服务]
核心算法:
public class URLShortener {
private static final String BASE62 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private static final int BASE = 62;
// 将数字ID转换为短码
public String encode(long id) {
StringBuilder sb = new StringBuilder();
while (id > 0) {
sb.append(BASE62.charAt((int)(id % BASE)));
id /= BASE;
}
return sb.reverse().toString();
}
// 将短码转换为数字ID
public long decode(String shortUrl) {
long id = 0;
for (char c : shortUrl.toCharArray()) {
id = id * BASE + BASE62.indexOf(c);
}
return id;
}
}
数据库设计:
CREATE TABLE urls (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
original_url VARCHAR(2048) NOT NULL,
short_code VARCHAR(10) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP,
click_count INT DEFAULT 0,
INDEX idx_short_code (short_code)
);
# 2. 设计聊天系统
需求分析:
- 一对一聊天
- 群组聊天
- 在线状态显示
- 消息历史存储
- 推送通知
系统架构:
[移动客户端] ←→ [WebSocket网关] ←→ [消息服务] ←→ [消息队列] ←→ [数据库] ↓ [推送服务]
消息服务设计:
@Service
public class MessageService {
@Autowired
private MessageRepository messageRepository;
@Autowired
private WebSocketService webSocketService;
public void sendMessage(SendMessageRequest request) {
// 1. 验证用户权限
validateUserPermission(request.getSenderId(), request.getChatId());
// 2. 创建消息
Message message = createMessage(request);
// 3. 存储消息
messageRepository.save(message);
// 4. 实时推送
List<String> recipients = getChatMembers(request.getChatId());
webSocketService.broadcastMessage(recipients, message);
// 5. 离线推送
pushOfflineNotification(recipients, message);
}
private Message createMessage(SendMessageRequest request) {
return Message.builder()
.id(generateMessageId())
.chatId(request.getChatId())
.senderId(request.getSenderId())
.content(request.getContent())
.messageType(request.getMessageType())
.timestamp(System.currentTimeMillis())
.build();
}
}
# 3. 设计新闻推荐系统
需求分析:
- 个性化推荐
- 实时热点推荐
- 多样性保证
- A/B测试支持
推荐算法:
@Component
public class NewsRecommendationEngine {
public List<News> recommend(String userId, int count) {
// 1. 获取用户画像
UserProfile profile = userProfileService.getUserProfile(userId);
// 2. 候选新闻召回
List<News> candidates = recallCandidates(profile);
// 3. 特征工程
List<NewsFeature> features = extractFeatures(candidates, profile);
// 4. 模型预测
List<ScoredNews> scoredNews = mlModelService.predict(features);
// 5. 重排序(考虑多样性)
List<News> reranked = rerank(scoredNews, profile);
return reranked.subList(0, Math.min(count, reranked.size()));
}
private List<News> recallCandidates(UserProfile profile) {
List<News> candidates = new ArrayList<>();
// 协同过滤召回
candidates.addAll(collaborativeFiltering.recall(profile));
// 内容召回
candidates.addAll(contentBasedFiltering.recall(profile));
// 热点召回
candidates.addAll(trendingNewsService.getTrendingNews());
return deduplicateAndFilter(candidates);
}
}
# 4. 设计分布式缓存系统
需求分析:
- 高性能读写
- 数据分片
- 故障转移
- 数据一致性
一致性哈希实现:
public class ConsistentHashing {
private final SortedMap<Integer, String> ring = new TreeMap<>();
private final int virtualNodes;
public ConsistentHashing(List<String> nodes, int virtualNodes) {
this.virtualNodes = virtualNodes;
for (String node : nodes) {
addNode(node);
}
}
public void addNode(String node) {
for (int i = 0; i < virtualNodes; i++) {
int hash = hash(node + ":" + i);
ring.put(hash, node);
}
}
public void removeNode(String node) {
for (int i = 0; i < virtualNodes; i++) {
int hash = hash(node + ":" + i);
ring.remove(hash);
}
}
public String getNode(String key) {
if (ring.isEmpty()) {
return null;
}
int hash = hash(key);
SortedMap<Integer, String> tailMap = ring.tailMap(hash);
int nodeHash = tailMap.isEmpty() ? ring.firstKey() : tailMap.firstKey();
return ring.get(nodeHash);
}
private int hash(String key) {
return key.hashCode();
}
}
# 🔧 系统设计面试技巧
# 1. 面试流程
- 需求澄清(5-10分钟)
- 容量估算(5-10分钟)
- 系统设计(10-15分钟)
- 详细设计(10-15分钟)
- 扩展讨论(5-10分钟)
# 2. 设计要点
- 从简单开始:先设计基本功能,再考虑扩展
- 数据驱动:基于数据量和QPS进行设计决策
- 权衡取舍:明确说明设计选择的原因
- 可扩展性:考虑系统如何应对增长
# 3. 常用技术栈
- 负载均衡:Nginx、HAProxy、AWS ELB
- 缓存:Redis、Memcached、CDN
- 消息队列:Kafka、RabbitMQ、AWS SQS
- 数据库:MySQL、PostgreSQL、MongoDB、Cassandra
- 搜索:Elasticsearch、Solr
- 监控:Prometheus、Grafana、ELK Stack
# 📚 推荐资源
- 《设计数据密集型应用》
- 《大规模分布式存储系统》
- System Design Interview 系列
- 高可用架构技术博客