构建像 YouTube 这样的视频共享平台是一个经典的系统设计面试问题。

YouTube 每分钟处理超过 500 小时的内容上传,每天提供数十亿次视频流。

与静态文件共享服务不同,YouTube 将每次上传转换为数十种优化格式,实现从智能手机到 4K 电视的流畅播放,即使在慢速网络上也是如此。

YouTube 架构

核心挑战

以下是使 YouTube 从系统设计角度有趣的一些核心挑战:

  • 规模:EB 级存储,数百万并发观众
  • 全球覆盖:为全球用户提供低延迟
  • 自适应交付:根据网络速度自动调整质量
  • 处理复杂性:每次上传变成 6+ 分辨率 × 数百个片段
  • 读重流量:需要激进缓存

类似的架构模式出现在 Netflix、Twitch 和 TikTok 等平台,以及任何大规模提供视频的平台。

面试需求澄清

让我们学习在系统设计面试中如何设计 YouTube:

1. 规模

  • 候选人:我们设计什么规模?
  • 面试官:每天 100 万次上传,1 亿日活用户
  • 为什么重要:规模驱动分片、分区和缓存
  • 面试洞察:你展示理解容量规划

2. 读写比

  • 候选人:读写比是多少?
  • 面试官:大约 100 次观看对应 1 次上传
  • 为什么重要:这是读重系统,所以设计偏向流媒体
  • 面试洞察:你展示对工作负载模式的认识

3. 文件大小

  • 候选人:最大视频文件大小是多少?
  • 面试官:256 GB
  • 为什么重要:强制使用多部分上传和分块
  • 面试洞察:你考虑边缘情况

4. 格式支持

  • 候选人:我们支持什么视频格式和分辨率?
  • 面试官:MP4、AVI、MOV,从 240p 到 4K
  • 为什么重要:需要强大的转码管道和多种输出版本
  • 面试洞察:你关注现实世界约束

5. 延迟目标

  • 候选人:流媒体的目标延迟是多少?
  • 面试官:首帧低于 500ms
  • 为什么重要:需要 CDN 和自适应流媒体
  • 面试洞察:你关注用户体验

6. 处理时间

  • 候选人:上传处理时间的可接受范围是什么?
  • 面试官:大约 10 到 30 分钟
  • 为什么重要:处理可以是异步的
  • 面试洞察:你理解最终一致性

7. 一致性

  • 候选人:新上传的最终一致性可以吗?
  • 面试官:是的,短暂延迟可以接受
  • 为什么重要:可用性优于严格即时性
  • 面试洞察:你展示 CAP 定理推理

8. 正常运行时间

  • 候选人:我们的正常运行时间目标是什么?
  • 面试官:99.9%
  • 为什么重要:需要冗余和故障转移
  • 面试洞察:你考虑可靠性

9. 直播

  • 候选人:我们支持直播吗?
  • 面试官:对于这次面试,专注于上传
  • 为什么重要:保持范围可控
  • 面试洞察:你避免功能蔓延

功能需求

上传视频

  • 用户从 Web 和移动客户端上传
  • 系统接受高达 256 GB 的文件
  • 无需数据丢失即可恢复中断的上传
  • 为转码管道存储原始媒体

流媒体视频

  • 跨地区和设备的流畅播放
  • 质量自动适应网络速度(自适应比特率)
  • 首帧在 500ms 内出现
  • 在不同连接类型下稳定

搜索视频

  • 通过查询标题和描述发现内容
  • 以可管理的块返回结果(分页)
  • 支持高基数搜索(数百万视频)

可用性

  • 服务在故障期间必须保持可用
  • 新上传不需要即时可见性(最终一致性可以)

可扩展性

  • 支持每天 100 万次上传
  • 处理 1 亿日活用户

大文件支持

  • 多部分上传,具有块级重试
  • 中断上传的恢复能力
  • 高效存储和处理大文件
  • 网络故障时无进度丢失

低延迟流媒体

  • 首帧必须在 500ms 内出现
  • 视频播放必须适应不同的网络速度
  • 正常网络条件下缓冲应该最小

低带宽使用

  • 为慢速网络自动调整质量
  • 更小的片段大小以实现稳定播放
  • 为发展中地区优化带宽

API 设计

API 类型:REST(表述性状态转移)。

为什么:REST 是面向公共 Web 服务的行业标准,为 Web 和移动客户端提供可扩展性和易于集成。

预签名 URL(绕过应用服务器)

客户端不通过 API 服务器上传视频,而是接收临时的、签名的 S3 URL。这防止应用服务器成为瓶颈。用户直接上传到 blob 存储。

分页

搜索和评论端点通过基于游标的分块返回结果。这防止大规模查询锁定数据库。

核心端点

1. POST /v1/videos

描述:服务器预留视频 ID 并返回预签名 URL,一个临时链接,允许客户端直接上传到 S3 而无需接触应用服务器。

示例请求

POST /v1/videos
Content-Type: application/json
{
"title": "My Video",
"description": "..."
}

示例响应

{
"video_id": "abc123",
"upload_url": "https://s3.amazonaws.com/...",
"expires_at": "2024-01-01T00:00:00Z"
}

应用服务器几乎未触及……带宽直接流向 blob 存储。

2. GET /v1/videos/{video_id}

描述:当用户请求观看视频时,此端点返回视频的元数据和清单文件 URL。客户端使用它开始自适应比特率流媒体(ABR)从 CDN。

示例响应

{
"video_id": "abc123",
"title": "My Video",
"manifest_url": "https://cdn.example.com/manifest.m3u8",
"duration": 300
}

清单文件告诉客户端哪些视频片段和分辨率可用。CDN 处理实际流媒体。

3. POST /v1/progress/{video_id}

描述:此端点跟踪用户的播放位置。它设计用于大规模(处理数百万写入/秒)并优先考虑速度而非即时一致性。

示例请求

POST /v1/progress/abc123
{
"position": 120,
"timestamp": 1699189200000
}

仅这个端点就处理数百万写入/秒。它不能承受延迟。所以发送请求;不要等待确认。然后存储在高吞吐数据库中如 DynamoDB。

4. GET /v1/search

描述:查询搜索索引以查找与用户查询匹配的视频。此端点严重依赖分页以可管理的块返回结果。

示例请求

GET /v1/search?q=keyword&cursor=abc123&limit=20

基于游标的分页防止大规模查询。每页包含一个 next_cursor 令牌,允许客户端获取下一批而无需重新查询整个数据集。

基于游标的分页比基于偏移的分页更具可扩展性。它防止”跳过 1000 万行”问题。

本文为学习目的的个人翻译,译文仅供参考。

原文链接:YouTube System Design

版权归原作者或原刊登方所有。本文为非官方译本;如有不妥,请联系删除。