Step 1 - 明确需求

以下是一些可供参考的讨论点:

  1. 主要特性是什么?=> 支持上传和下载文件,文件同步,以及通知。
  2. 移动端 or web应用 or both ? => both。
  3. 支持哪些文件类型?=> 所有类型。
  4. 文件需要加密存储吗?=> 需要。
  5. 文件大小有限制吗?=> 不超过10GB。
  6. 日活多少?=>1000万。

这里以下列需求作为设计目标:

  • 上传文件。
  • 下载文件。
  • 多端自动同步。
  • 文件历史记录。
  • 文件分享。
  • 当文件被修改,删除,或被共享给你时,发送推送消息。

以下特性暂不支持:

  • 文档在线协作。

除以上需求外,非功能性需求也要得到保证:

  • 可靠性,绝不能导致数据丢失。
  • 快速同步。
  • 带宽友好,不能太占用带宽。
  • 可扩展,能够支持大流量并发。
  • 高可用性,即使服务器掉线,用户也需要能够使用部分功能,比如编辑本地文件。

规模预估:

  • 假设应用有5000万注册用户以及1000万日活用户。
  • 每位用户有10GB免费使用空间。
  • 假设用户平均每天上传2个文件,文件平均大小为500KB。
  • 读写比例为1:1。
  • 总空间占用:5000万 * 10GB = 500PB。
  • 上传QPS:1000万 * 2 / 24 / 3600 ~= 240
  • 峰值上传QPS:QPS * 2 = 480

Step 2 - 高阶设计

从单服务器开始,逐渐将系统拓展到支持百万级用户。单服务器设计如下:

  • 一台服务器用于上传和下载文件。
  • 一个数据库用于保存元数据,比如用户配置,登录信息,文件信息等。
  • 一个文件存储系统用于存储文件。

简单地使用一台Apache web服务器和MySql数据库,以及一个本地路径 drive/ 作为根目录即可实现上面的系统。在 drive/ 目录下,每个用户对应一个文件夹,每个文件夹存储对应用户的文件,文件名与用户上传的原始文件名相同。以下是这个系统的示例:

API设计

主要需要3个API:上传文件,下载文件,获取文件历史 。

1. 上传文件

包含两种上传:

  • 简单上传,适合小文件
  • 断点重传,适合大文件

以下是一个断点重传的API示例:

https://api.example.com/files/upload?uploadType=resumable

包含上传类型和本地文件数据两个参数。

一次断点重传的流程如下:

  • 发送初始请求以获取重传URL。
  • 上传文件,监测上传进度。
  • 如果上传被打断,则恢复传输。

2.下载文件

示例API: https://api.example.com/files/download

参数:

  • path: 文件路径

示例参数:

{
    "path": "/recipes/soup/best_soup.txt"
}

3.获取文件历史记录

示例API: https://api.example.com/files/list_revisions

参数:

  • path: 文件路径
  • limit: 返回的最大历史记录数


以上所有的API都需要支持HTTPS,以保证数据是加密传输。

多服务器设计

与其自建服务器分片与复制,不如将数据存储交给现有的云服务商来实现,这样可以借助云服务商成熟的服务和多数据中心来保障数据安全。以Amazon S3为例,Amazon S3支持同数据中心内的数据库复制和跨数据中心的数据库复制,通过将数据在多地进行冗余备份,可以有效保证数据安全及服务可用。

除了多地备份外,以下措施也必不可少:

  • 负载均衡:增加负载均衡以平均分布网络流量,以及容错。
  • Web服务器集群:根据流量动态添加或删除服务器。
  • 元数据库:将数据库独立出来,以避免单点故障,同时,使用分片和数据库复制技术,以实现可用性和扩展需求。
  • 文件存储:使用Amazon S3来存储文件,为了保证可用性和可靠性,可以将文件在两地进行冗余备份存储。

经过以上措施的优化后,系统设计调整如下:


同步冲突

当两个用户同时修改了同一个文件时,冲突发生。这里我们以第一次修改提交为准,第二次提交被视为冲突,如下:

当用户2收到冲突通知时,服务器会一并返回服务器上最新的版本,由用户2自己来解决冲突。





























  • 无标签