Skip to content

第 15 章:设计 Google Drive

引言

Google Drive 是一种云端文件存储与同步服务,让用户能够通过不同设备存储、访问和共享文件。本章讨论如何设计具备以下功能的可扩展系统:

  • 文件上传与下载
  • 跨设备文件同步
  • 文件共享
  • 文件版本历史
  • 编辑、删除和共享通知

第 1 步:理解问题

核心需求

功能需求:

  • 上传和下载文件。
  • 在多台设备之间同步文件。
  • 保留文件历史版本。
  • 支持带权限控制的文件共享。
  • 在文件编辑、删除和共享时发送通知。

非功能需求:

  • 可靠性: 不能丢失数据。
  • 同步速度快: 避免同步延迟让用户久等。
  • 带宽效率: 尽量减少不必要的数据传输。
  • 可扩展性: 支撑 1000 万日活跃用户(DAU)。
  • 高可用性: 在服务器故障或网络问题发生时仍能运行。

约束与假设

  • 每位用户获得 10 GB 免费空间
  • 文件大小上限:10 GB
  • 平均上传文件大小:500 KB
  • 每位用户每天上传 2 个文件
  • 所需总存储容量:500 PB

第 2 步:概要设计

单服务器方案

一个基础方案包含:

  1. Web 服务器: 处理上传和下载。

  2. 元数据数据库: 记录用户数据、登录信息和文件信息等元数据。

  3. 存储目录: 按命名空间组织文件。

    命名空间
  • 设置 Web 服务器,并以 drive/ 目录作为上传文件的根目录。
  • drive/ 下包含一组称为命名空间的目录。
  • 每个命名空间存放对应用户上传的所有文件。
  • 通过命名空间与相对路径的组合,可以唯一标识每个文件或文件夹。

这个方案可以作为起点,但无法满足规模扩展的需要。

API

  1. 向 Google Drive 上传文件: 支持两种上传方式。
  2. 从 Google Drive 下载文件:
  3. 获取文件历史版本:

迁移到分布式系统

改进措施:

  1. 分片: 根据 user_id 将存储分散到多台服务器。

  2. Amazon S3: 使用 S3 提供可扩展、具备冗余能力的文件存储,并进行跨区域复制。

    复制
  3. 负载均衡器: 将流量分配到多台 Web 服务器。

  4. 元数据数据库复制: 通过数据库分片和复制保证可用性。

同步冲突:

对于 Google Drive 这样的大型存储系统,同步冲突时有发生。当两位用户同时修改同一个文件或文件夹时,就会产生冲突。

同步冲突
  • 例如,用户 1 和用户 2 同时更新同一文件,但系统先处理了用户 1 的文件。
  • 用户 1 的更新成功,用户 2 则遇到同步冲突。
  • 系统提供同一文件的两个副本:用户 2 的本地副本以及服务器上的最新版本。
  • 用户 2 可以合并两个文件,或用其中一个版本覆盖另一个。

改进后的设计

概要设计
  1. 用户交互: 用户通过浏览器或移动应用访问服务。

  2. 数据块服务器:

    • 将文件切分为最大 4 MB 的数据块,并为每块生成唯一的哈希值。
    • 将数据块独立存放在云存储中,例如 Amazon S3。
    • 按特定顺序拼接数据块,还原文件。
  3. 云存储: 存储数据块,提供可扩展性和冗余能力。

  4. 冷存储: 将不活跃文件迁移到冷存储,降低成本。

  5. 负载均衡器: 在 API 服务器之间均匀分配请求,保证高效运行。

  6. API 服务器:

    • 处理用户认证、个人资料管理及文件元数据更新。
    • 管理上传之外的所有工作流。
  7. 元数据数据库与缓存:

    • 存储用户、文件、数据块及版本的元数据。
    • 缓存经常访问的元数据,以加快读取速度。
  8. 通知服务:

    • 使用发布/订阅系统通知客户端文件变更(添加、编辑、删除)。
    • 让客户端能够拉取最新更新。
  9. 离线备份队列: 暂存文件变更信息,供离线客户端重新上线后同步。


第 3 步:深入设计

元数据数据库

下面展示的模型经过高度简化,仅包含最重要的表和字段。

表结构设计:

  • 用户表: 存储用户资料和偏好设置。
  • 文件表: 保存文件元数据,例如大小、名称和路径。
  • 数据块表: 跟踪数据块,以便还原文件。
  • 文件版本表: 存储文件版本历史。
元数据数据库

文件上传流程

  1. 上传文件:
    • 数据块服务器将文件切块、压缩并加密。
    • 数据块上传到数据块服务器,并存入 S3。
  2. 上传元数据:
    • 客户端向 API 服务器发送元数据。
    • 元数据以 pending 状态存入数据库。
  3. 完成上传:
    • S3 触发回调,把文件状态更新为 uploaded
    • 通知服务告知相关用户。
上传流程

文件同步

  1. 增量同步: 只传输修改过的数据块,而非整个文件。

    增量同步
  2. 压缩: 根据文件类型选用压缩算法压缩数据块。

  3. 冲突解决:

    • 先处理的版本生效。
    • 冲突版本分别保存,交由用户解决。
文件同步

文件下载流程

当文件在别处被添加或修改时,就会触发下载流程。客户端可以通过两种方式得知变更:

  • 若其他客户端修改文件时客户端 A 在线,通知服务会通知客户端 A。
  • 若当时客户端 A 离线,变更数据会保存在缓存中。客户端重新上线后会拉取最新变更。

客户端获知文件变更后,先通过 API 服务器请求元数据,再下载数据块并还原文件。

  1. 触发: 通知服务告知客户端文件已更新。
  2. 获取元数据: 客户端通过 API 获取更新后的元数据。
  3. 下载数据块: 客户端从数据块服务器下载更新的数据块并还原文件。
下载流程

通知服务

  1. 目的: 让客户端及时获知文件变更。
  2. 机制: 采用长轮询实现异步通知。
  3. 示例: 文件添加、编辑或删除后,将通知推送给所有相关客户端。

存储优化

  1. 去重: 在账户范围内通过哈希比较移除重复数据块。
  2. 版本管理策略:
    • 限制保存的历史版本数量。
    • 对频繁编辑的文件优先保留近期版本。
  3. 冷存储: 将很少访问的文件迁移到成本更低的存储方案,例如 Amazon S3 Glacier。

故障处理

  1. 负载均衡器故障: 启用备用负载均衡器。
  2. 数据块服务器故障: 将待处理任务重新分配给其他服务器。
  3. 元数据数据库故障:
    • 将从节点提升为主节点。
    • 将流量重定向到仍可用的副本。
  4. 云存储故障: 借助跨区域复制读取不可用的文件。
  5. 通知服务故障: 客户端重新连接其他服务器。