Skip to content

本页使用系统设计方法论中的六步框架,完整走读四个高频面试案例。


案例一:秒杀系统

1. 需求澄清

  • 核心功能:限量商品在固定时间点开始售卖,用户抢购
  • 高并发写入:库存扣减须保证不超卖
  • 读多写少:活动开始前大量用户刷新页面,写请求集中在开始瞬间
  • 非功能要求:高可用、低延迟、防作弊

2. 容量估算

指标数值
峰值并发用户100,000
峰值写 QPS(下单)10,000
峰值读 QPS(查库存/页面)100,000
库存数量(示例)1,000 件
  • 库存数据量极小,完全可以放入 Redis 内存
  • 订单写入需异步削峰,DB 不直接承受 10K QPS

3. 高层设计

用户 → CDN(静态资源)
     → Nginx 负载均衡
       → 限流层(令牌桶 / Redis 计数)
         → 订单服务(Order Service)
           → 库存服务(Inventory Service)──→ Redis(原子扣减)
                                         ──→ MQ(Kafka/RocketMQ)
                                               → DB(MySQL 最终落盘)

4. 详细设计

库存预热

活动开始前将库存写入 Redis:

bash
SET stock:{itemId} 1000

原子扣减(Lua 脚本)

使用 Lua 脚本保证"检查 + 扣减"的原子性,彻底避免超卖:

lua
local stock = tonumber(redis.call('GET', KEYS[1]))
if stock <= 0 then
    return -1  -- 库存不足
end
redis.call('DECR', KEYS[1])
return stock - 1

异步下单流程

  1. 库存扣减成功后,向 MQ 发送订单创建消息
  2. 订单消费者异步写入 MySQL,生成正式订单
  3. 用户通过轮询或 WebSocket 获取下单结果

防作弊措施

  • 请求携带活动 Token,服务端校验一次性有效
  • 同一用户 ID 限购一件,Redis SETNX user:{userId}:{itemId} 去重
  • 前端随机延迟 + 验证码,打散流量峰值

5. 扩展与优化

  • Redis 集群:库存分片,水平扩展读写能力
  • MQ 削峰:Kafka 分区并行消费,订单服务无状态横向扩展
  • 本地缓存:Nginx/应用层缓存活动配置,减少 Redis 压力
  • 限流降级:令牌桶限流,超出流量直接返回"活动火爆,请稍后重试"

6. 权衡讨论

方案优点缺点
强一致(DB 行锁)绝对不超卖并发极低,性能瓶颈
Redis 原子扣减 + MQ高吞吐,不超卖最终一致,需处理消息失败补偿
预扣库存 + 超卖补偿吞吐最高实现复杂,需业务兜底

面试要点:重点说明 Lua 脚本原子性如何解决超卖,以及 MQ 带来的最终一致性挑战(消息幂等、失败重试)。


案例二:即时通讯系统(IM)

1. 需求澄清

  • 支持单聊、群聊(上限 500 人)
  • 在线状态显示
  • 消息历史记录(可查询最近 N 条)
  • 离线推送通知(APNs / FCM)
  • 消息送达回执(已发送、已送达、已读)

2. 容量估算

指标数值
DAU10,000,000
人均发消息数/天50 条
每日消息总量5 亿条
峰值 QPS(发消息)~6,000
P99 消息延迟目标< 200ms
消息存储(按 1 年)~100 TB

3. 高层设计

客户端 ←──WebSocket──→ WebSocket 网关(Gateway)

                    消息服务(Message Service)
                     ↙            ↘
          消息存储                推送服务
       (Cassandra/HBase)      (APNs / FCM)

                  在线状态
                   (Redis)

4. 详细设计

WebSocket 连接管理

  • 每台 Gateway 节点维护本地连接表 { userId → socket }
  • 同时在 Redis 记录路由信息:HSET gateway:user {userId} {gatewayNodeId}
  • 消息路由时先查 Redis 找到目标 Gateway 节点,再通过内部 RPC 转发

单聊消息投递流程

发送方 ─→ Gateway A ─→ Message Service
                          ├─ 写 Cassandra(持久化)
                          ├─ 查 Redis 路由(接收方在哪个 Gateway)
                          ├─ 若在线:RPC → Gateway B → 推送 WebSocket
                          └─ 若离线:写推送队列 → APNs/FCM

群聊 Fan-out 策略

策略适用场景说明
写扩散(Fan-out on Write)小群(< 200 人)发消息时同步写入每个成员的消息队列
读扩散(Fan-out on Read)大群 / 超级群消息只写一份,成员读取时拉取

实践中采用混合策略:群成员数小于阈值用写扩散,超过后切换读扩散。

消息存储(Cassandra)

表结构(按会话分区,时间排序):
  partition key: conversationId
  clustering key: messageId(基于时间的 Snowflake ID,降序)
  columns: senderId, content, type, timestamp, status
  • 查询最近消息:SELECT * FROM messages WHERE conversationId=? LIMIT 50
  • 消息 ID 使用全局唯一且有序的 Snowflake ID,便于排序与去重

在线状态

  • 客户端每 30 秒发送心跳,Gateway 刷新 Redis TTL:SETEX online:{userId} 60 {gatewayId}
  • TTL 过期即视为离线,避免状态不一致

消息回执

  • 已送达:接收方 Gateway 收到消息后回 ACK,Message Service 更新状态
  • 已读:接收方打开会话后发送 Read Receipt 事件

5. 扩展与优化

  • Gateway 水平扩展:无状态,WebSocket 连接通过 L4 负载均衡分发
  • Message Service 分区:按 conversationId 哈希路由,保证同一会话消息有序
  • Cassandra 分片:自动分片,写入吞吐随节点数线性扩展
  • 推送合并:离线期间多条消息合并为一条推送,减少唤醒次数

6. 权衡讨论

方案优点缺点
写扩散读取简单,延迟低大群写放大严重
读扩散写入压力小读取需聚合,延迟高
混合策略兼顾两者实现复杂,阈值需调优

面试要点:重点讨论大群消息的 Fan-out 策略选择,以及 WebSocket 网关的连接路由机制。


案例三:Feed 流 / Timeline

1. 需求澄清

  • Twitter 类时间线:关注的人发布的内容按时间倒序展示
  • 支持发帖、关注、取消关注
  • 时间线近实时更新
  • 读写比例约 20:1(读多写少)

2. 容量估算

指标数值
DAU100,000,000
人均发帖/天1 条
日发帖总量1 亿条
人均读 Feed/天20 次
峰值读 QPS~500,000
峰值写 QPS~25,000

3. 高层设计

发帖:Post Service → Fan-out Service → Timeline Cache(Redis)
                                     → 持久化存储(MySQL/Cassandra)

读取:Feed Service → Timeline Cache(Redis)→ 返回用户时间线
                  → (缓存 miss)→ 持久化存储重建

4. 详细设计

三种 Fan-out 模型

推模型(Push / Fan-out on Write)

发帖时立即将帖子 ID 写入所有粉丝的 Timeline Cache:

发帖 → Fan-out Service → 遍历粉丝列表
                        → ZADD timeline:{followerId} {timestamp} {postId}
                        → ZREMRANGEBYRANK timeline:{followerId} 0 -1001  (保留最新 1000 条)
  • 优点:读取 O(1),延迟极低
  • 缺点:大 V(粉丝百万级)发帖时写放大严重

拉模型(Pull / Fan-out on Read)

读取时实时合并关注列表中每个人的最新帖子:

读取 → 获取关注列表 → 并行查询每个人的最新帖子 → 归并排序 → 返回
  • 优点:写入简单,无写放大
  • 缺点:读取耗时高,关注人数多时延迟不可控

混合模型(Hybrid)

  • 普通用户(粉丝 < 100K):推模型,发帖后 Fan-out 到粉丝 Timeline Cache
  • 大 V(粉丝 ≥ 100K):拉模型,Timeline Cache 中只存普通用户帖子
  • 读取时:Timeline Cache(普通用户帖子) + 实时拉取已关注大 V 的最新帖子 → 归并

Redis ZSET Timeline

bash
# 写入帖子
ZADD timeline:{userId} {timestamp} {postId}

# 读取最新 20 条
ZREVRANGEBYSCORE timeline:{userId} +inf -inf LIMIT 0 20

# 控制缓存大小,保留最新 1000 条
ZREMRANGEBYRANK timeline:{userId} 0 -1001

帖子内容存储

  • 帖子元数据(作者、时间、文本)存 MySQL,按 postId 查询
  • 图片/视频资源存对象存储(S3),通过 CDN 加速

5. 扩展与优化

  • Fan-out 异步化:大量粉丝的 Fan-out 通过 Kafka 异步处理,避免发帖接口超时
  • Timeline Cache 冷启动:用户长时间未登录后 Cache 过期,首次读取触发异步重建
  • 热点帖子缓存:爆款内容单独缓存,减少 DB 压力
  • 地理分布:多 Region 部署,就近读取

6. 权衡讨论

方案读延迟写开销适用场景
纯推模型极低高(大 V 写放大)粉丝数均匀的平台
纯拉模型写多读少,关注数少
混合模型适中存在大 V 的社交平台

面试要点:清晰解释混合模型中大 V 的判断阈值及切换机制,以及 ZSET 裁剪策略对存储的控制。


案例四:短视频推荐系统

1. 需求澄清

  • 个性化视频 Feed,无限下拉
  • 冷启动(新用户/新视频)处理
  • 内容安全审核
  • 支持 A/B 实验
  • 非功能:推荐延迟 < 200ms,结果多样性

2. 容量估算

指标数值
DAU50,000,000
人均观看视频/天100 条
每日推荐请求量50 亿次
峰值推荐 QPS~100,000
视频库规模10 亿+

3. 高层设计

客户端
  → API Gateway
    → 推荐服务(Recommendation Service)
        ├─ 召回层(Recall):从海量视频中初筛候选集
        ├─ 排序层(Rank):ML 模型精排
        └─ 重排层(Re-rank):多样性 + 业务规则
    → 视频服务(Video Service):获取视频元数据
    → CDN:视频流分发

4. 详细设计

推荐三层漏斗

视频库(10亿)
    ↓ 召回(多路)
候选集(~10,000)
    ↓ 粗排(轻量模型)
候选集(~1,000)
    ↓ 精排(重模型)
候选集(~100)
    ↓ 重排(多样性 + 规则)
最终推荐列表(20 条)

召回层(多路召回)

召回通道说明
协同过滤相似用户喜欢的视频
内容相似与历史观看视频相似的内容
热门召回当前热门视频兜底
关注博主已关注账号的最新发布
探索召回随机探索,解决信息茧房

排序层(ML 模型)

  • 特征维度:用户特征(历史行为、画像)、视频特征(标签、时长、完播率)、上下文特征(时间、设备、网络)
  • 预测目标:完播率、点赞率、分享率的加权综合分
  • 模型部署:TensorFlow Serving / Triton,GPU 推理加速

重排层

  • 多样性:同一作者/标签的视频不连续出现(Sliding Window 去重)
  • 已看过滤:Bloom Filter 过滤近期已推送视频
  • 业务规则:广告位插入、违规内容降权、新人扶持
  • 时效性:优先推送 24 小时内的新视频

实时特征更新(Flink)

用户行为事件(Kafka)
  → Flink 实时计算
    → 更新实时特征(Redis):短期兴趣、近 1 小时完播率
    → 更新离线特征(Hive):长期画像,次日生效

内容审核流水线

视频上传 → 转码服务
         → 审核服务(OCR + 音频识别 + 图像分类)
           ├─ 机器初审(秒级)
           └─ 人工复审(分钟级)
         → 审核通过 → 进入推荐候选池

A/B 实验

  • 用户按 userId 哈希分桶,不同桶命中不同实验组
  • 实验配置中心实时下发,推荐服务读取对应策略
  • 指标监控:完播率、CTR、留存率,统计显著后全量

5. 扩展与优化

  • 预计算推荐列表:离线预生成部分用户的推荐列表缓存到 Redis,降低在线延迟
  • 模型蒸馏:将大模型知识蒸馏到轻量模型,降低推理延迟
  • 召回并行化:多路召回并行请求,取并集后去重,控制总耗时
  • CDN 预加载:推荐返回后,客户端预加载下一屏视频,提升体验

6. 权衡讨论

维度选项 A选项 B取舍
实时 vs 批量特征实时(Flink):低延迟、捕捉瞬时兴趣批量(Hive):高质量、稳定混合:实时特征捕捉短期兴趣,批量特征描述长期画像
参与度 vs 多样性纯优化 CTR:信息茧房风险强制多样性:短期指标下降重排层引入多样性惩罚项,长期留存更优
质量 vs 延迟重模型精排:效果好,耗时长轻模型:延迟低,效果差粗排用轻模型缩小候选集,精排只处理 1000 条

面试要点:清晰描述三层漏斗架构(召回 → 排序 → 重排),解释各层的目标与技术选型;重点讨论冷启动问题(新用户用热门召回 + 探索,新视频用内容召回 + 流量扶持)。