Meta 的 system design 面试有非常清晰的出题规律:数据强一致、系统低延迟、功能对齐产品体验。无论题目表面看似社交、内容分发还是存储系统,考察核心永远围绕三个维度——用户规模(scale)、一致性策略(consistency tradeoff)、延迟预算(latency)。
这篇文章拆解 Meta 最高频的三道系统设计题,并给出一套可直接复用的复盘框架。
复盘一道题的正确姿势
- 定义核心交互:用一句话说清系统的核心用户操作路径
- 估算容量:QPS、存储与延迟预算
- 画数据流与控制流:write path 和 read path,识别缓存、数据库、消息系统之间的边界
- 展开权衡:通过一到两个 trade-off 深入讨论,例如 read-fanout 与 write-fanout 的取舍
高频题一:News Feed(fanout 与实时性权衡)
Feed 系统是 Meta 的经典高频题,核心考察 fanout 与实时性的权衡。产品层面,一个用户发帖意味着几百万粉丝的 timeline 需要更新;系统层面,这对应一次写入触发大量下游数据变动。
push + pull 混合模型
Meta 的设计传统是 push + pull 混合:
- 高活跃用户(如名人账号):写入时只做轻量 fanout,将帖子存入 global post store;读取时由 follower 的 newsfeed 服务执行 lazy pull 聚合
- 普通用户:写入时直接 fanout 到 follower 的 timeline(write-fanout),读取时直接命中
def deliver_post(post, author):
save_to_global_store(post)
if author.follower_count > CELEBRITY_THRESHOLD:
# 名人:只入全局库,读取时 pull
return "pull"
else:
# 普通用户:写时 fanout 到粉丝 timeline
for fan in author.followers:
timeline_cache[fan].push(post.id)
return "push"
加分点:ranker pipeline 解耦
面试中要强调 ranking pipeline 的解耦:一个快速排序模型在 serving 层执行,另一个复杂 ML 模型在离线训练中更新特征与权重。展示这一点能体现对 production-scale 系统的理解深度。
高频题二:Messenger / Chat(消息一致性与投递语义)
Chat 题考点集中在消息一致性与 delivery semantics。Meta 的即时通讯采用 multi-device synchronization model,要求消息在不同设备间按时间一致显示,同时保证「已送达」「已读」状态准确。
store-and-forward 处理离线消息
面试官常追问离线消息如何处理。核心是 store-and-forward 机制:
- 目标用户离线时,delivery service 将消息暂存在 Redis 或持久队列,并记录 offset
- 用户重新上线后,client 从 offset 处继续拉取,保证不丢不重
def deliver_message(msg, recipient):
if is_online(recipient):
push_to_device(recipient, msg)
else:
# 离线:暂存并记录 offset
offline_queue[recipient].append(msg)
update_offset(recipient, msg.seq)
def on_reconnect(recipient):
last = get_offset(recipient)
return [m for m in offline_queue[recipient] if m.seq > last]
最后要讨论 end-to-end 加密与多设备密钥同步,体现对隐私和安全的考量。
高频题三:秒杀 / 座位预订(防 double booking 的分布式锁)
这道题常出现在 Meta 的 infrastructure 或 commerce 团队面试,考察重点是防止 double booking 的分布式锁设计。把系统建模为「稀缺资源分配问题」:多个用户同时请求同一座位/房间,系统必须在高并发下保持唯一性。
reservation token + TTL-based lock
标准思路是 reservation token + TTL 锁:
- 用户点击预订时,系统生成带过期时间的 token 写入 Redis,作为 seat_id 的唯一持有者
- 若确认购买,将锁升级为持久状态写入数据库;否则 TTL 过期自动释放
def try_reserve(seat_id, user_id, ttl=120):
# SET NX:只有 key 不存在时才设置,保证唯一持有者
ok = redis.set(f"lock:{seat_id}", user_id, nx=True, ex=ttl)
return bool(ok)
def confirm(seat_id, user_id):
holder = redis.get(f"lock:{seat_id}")
if holder == user_id:
persist_booking(seat_id, user_id) # 升级为持久状态
return True
return False # 锁已过期或被他人持有
若面试官追问跨分区一致性,可进一步说明用一致性哈希分片 seat_id、或引入 Redlock / 单调递增 fencing token 防止锁失效后的脏写。
三维度复盘速查表
| 维度 | News Feed | Chat | 预订 |
|---|---|---|---|
| Scale | 名人 fanout 放大 | 多设备同步 | 高并发抢占 |
| Consistency | 最终一致(timeline) | 顺序 + 不丢不重 | 强一致(唯一持有) |
| Latency | 读路径毫秒级 | 投递实时 | 锁获取低延迟 |
FAQ
Q1:Meta 系统设计面试最看重什么? 三个维度:scale(用户规模)、consistency(一致性取舍)、latency(延迟预算)。面试官不在乎你画多漂亮的架构图,而在乎你能否就一两个关键 trade-off 展开有深度的讨论。
Q2:News Feed 题该用 push 还是 pull? 混合模型最优:普通用户用 write-fanout(push),名人账号用 read-fanout(pull)避免写放大。能讲清两者切换的阈值和理由是加分点。
Q3:Chat 题怎么处理离线消息? 用 store-and-forward:离线时暂存到 Redis/持久队列并记录 offset,用户上线后从 offset 续拉,保证不丢不重。再补一句多设备同步和 E2E 加密会更完整。
Q4:秒杀/预订题如何防止 double booking? reservation token + TTL 锁:用 Redis SET NX 保证唯一持有者,确认后升级为持久状态,未确认则 TTL 自动释放。跨分区可用一致性哈希分片或 fencing token。
Q5:如何在 45 分钟内讲完一道 Meta 系统设计? 按四步走:一句话定义核心交互 → 估算容量 → 画 read/write path → 选一两个 trade-off 深入。时间紧时砍掉次要功能,把深度留给核心权衡。
正在准备 Meta 系统设计?
如果你能列组件但讲不深 trade-off,或想在 onsite 前把 News Feed / Chat / 预订三道高频题练到能临场展开,欢迎交流:可提供题型拆解、复盘框架与表达陪练,针对 Meta 设计轮的考察重点定制练习。
联系方式
需要面试真题与定制备战计划?立刻联系微信 Coding0201,获取真题。
Email: [email protected] Telegram: @OAVOProxy