系统设计题

# 系统设计题

# 🏗️ 系统设计基础

# 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. 面试流程

  1. 需求澄清(5-10分钟)
  2. 容量估算(5-10分钟)
  3. 系统设计(10-15分钟)
  4. 详细设计(10-15分钟)
  5. 扩展讨论(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 系列
  • 高可用架构技术博客