如何设计类似百度网盘的系统?-百度网盘的系统设计分析

在本文中,我们将设计一个Google Drive服务!! (类似百度网盘,所以标题取百度网盘应该没毛病。事实上不可能这么简单,有时间可以讨论以下百度网盘的网络架构)

系统设计是软件工程中最重要和最令人担忧的方面之一。很难理解软件体系结构书籍中使用的术语,并且没有明确的分步指南。 每个人似乎都有不同的方法。 当然,还有一个心理障碍是这些可能本来就很难理解。 因此,我根据自己学习架构课程的经验着手设计一个系统。让我们设计一种云文件存储服务,Google Drive。它是一个文件存储和同步服务,使用户可以将其数据存储在远程服务器上。

现在,那些已经使用过Google Drive的人知道我们可以从任何设备上传任何大小的文件,并且可以在我们的手机,笔记本电脑,个人计算机等设备上找到这些文件。我们很多人想知道该系统如何处理如此大量的文件。

★系统定义

我们需要澄清系统的目标。 系统设计是一个巨大的话题。如果我们不将其范围缩小到特定目的,那么设计系统就会变得复杂,尤其是对于新手。

用户应该能够从任何设备上载和下载文件/照片。并且文件将在用户登录的所有设备中同步。

如果考虑到服务中有1000万用户,每天有1亿个请求,那么写入和读取操作的数量将是巨大的。为简化起见,我们仅设计Google云端硬盘存储空间。换句话说,用户可以上传和下载文件,从而有效地将它们存储在云中。

★系统要求

在这一部分中,我们决定系统的功能。我们可以将这些要求分为两部分:

  • 功能要求:

    用户应该能够从任何设备上载和下载文件。并且文件将在用户登录的所有设备中同步。
    这些是系统的主要目标。这是系统必须交付的要求。

  • 非功能需求NFR:

    现在分析的更关键的要求。让我们定义我们的NFR:

    用户可以从任何设备上载和下载文件。该服务应支持存储最大1 GB的单个大文件。服务应在设备之间自动同步;如果一个文件是从设备上传的,则应在用户登录的所有设备上同步该文件。

★服务器端组件设计

对于系统设计的新手,请记住:“如果您对从哪里开始系统设计感到困惑,请尝试从数据流开始。”

我们在该系统中的用户可以上传和下载文件。用户从客户端应用程序/浏览器上载文件,服务器将存储它们。用户可以从服务器下载更新的文件。因此,让我们看看我们如何为如此大量的用户处理文件的上传和下载。

上传/下载文件:

从图中可以看到,如果我们上传完整大小的文件,则会浪费我们的存储和带宽。而且,延迟会增加以完成上载或下载。
在这里插入图片描述
图:完整文件传输需要更多时间,存储空间和带宽。

高效处理文件传输:

我们可以将每个文件分成较小的块。然后,我们只能更改数据的小片段,而不是整个文件。万一数据上传失败,该策略也将有所帮助。我们需要将每个文件划分为固定大小,例如2 MB。

在这里插入图片描述
图:将文件分成较小的块以优化存储利用率和带宽

我们的块大小需要更小。这将有助于优化空间利用率,而网络带宽是做出决定时的另一个考虑因素。元数据应包括每个文件的块信息的记录。

我们可以假设文件需要存储在2 MB的小块中。如果进程失败,则在文件较小的部分重试操作的情况下,我们也会受益。 如果未上传文件,则仅重试失败的块。

客户端和云存储之间较少的数据传输量将帮助我们获得更好的响应时间。不用发送整个文件,我们只需要发送文件的修改后的块。

在这里插入图片描述
图:仅传输更新的块

在这种情况下,文件的更新部分将被传输。我们将把文件分成2MB的块,并仅传输文件的修改部分,如下图所示。
从上图可以看到,我们没有更新整个10 MB的文件,而是更新了文件的修改后的2MB部分。它将为用户减少带宽消耗和云存储。最重要的是,响应时间将更快。

客户端离线时会发生什么?

客户端组件Watcher将观察客户端文件夹。如果用户发生任何更改,它将通知索引控制器(Index Controller,另一个客户端组件)有关用户操作的信息。它还将监视其他客户端(设备)是否发生任何更改,这些更改由Notification Server广播。

当元数据服务收到更新/上传请求时,它需要检查元数据数据库的一致性,然后继续进行更新。 之后,将向所有订阅的设备发送通知以报告文件更新。

元数据数据库:

我们需要一个负责保存有关文件,用户等信息的数据库。它可以是关系数据库,例如MySQL或NoSQL,例如MongoDB。我们需要将数据块,文件,用户信息等保存在数据库中。

众所周知, 我们必须在两种类型的数据库(SQL或NoSQL)之间进行选择。无论我们选择什么,我们都需要确保数据的一致性。

使用SQL数据库可以为我们提供同步实现的好处,因为它们支持ACID属性。

NoSQL数据库不支持ACID属性。但是它们提供了对可伸缩性和性能的支持。因此,我们需要在Metadata Server的逻辑中以编程方式为此类数据库提供对ACID属性的支持。

同步:
现在,客户端从设备更新文件。需要有一个组件来处理更新并将更改应用到其他设备。它需要同步客户端的本地数据库和远程元数据数据库。MetaData服务器可以执行这项工作来管理元数据并同步用户的文件。

消息队列:
现在考虑一下;如此大量的用户正在同时上传文件,服务器如何处理如此大量的请求。为了能够处理如此大量的请求,我们可能在客户端和服务器之间使用消息队列。

在这里插入图片描述
图:消息传递队列提供可伸缩的请求排队和更改通知,以使用pull或push策略支持大量客户端。

当目标程序忙或未连接时,消息队列提供临时消息存储。它提供了异步通信协议。它 是一种将消息放入队列并且不需要立即响应即可继续处理的系统。RabbitMQ,Apache Kafka等是消息传递队列的一些示例。

如果是消息队列,则一旦客户端接收到消息,就会从队列中删除消息。因此,我们需要为客户端的每个订阅的设备创建几个响应队列。

在这里插入图片描述
图:每种设备类型的响应消息队列

对于大量用户,我们需要一个可伸缩的消息队列,该队列支持客户端和同步服务之间基于异步消息的通信。该服务应该能够在高度可用,可靠和可伸缩的队列中有效地存储任意数量的消息。例如:apache Kafka,rabbitMQ等。

云储存:

如今,有许多平台和操作系统,例如智能手机,笔记本电脑,个人计算机等。它们可随时随地提供移动访问。

如果您将文件保存在笔记本电脑的本地存储中,并且出门在外但想在手机上使用它,那么如何获取数据?这就是为什么我们需要云存储作为解决方案。

它存储用户上传的文件(块)。客户端可以通过文件处理服务器与存储进行交互,以从存储发送和接收对象。它只保存文件;元数据DB保留块大小和文件编号的数据。

文件处理工作流程:

客户端A将块上传到云存储。客户端A使用元数据服务器更新元数据并提交对MetadataDB的更改。客户端得到确认,并将通知发送到同一用户的其他设备。其他设备接收元数据更改并从云存储下载更新的块。
在这里插入图片描述
图:客户端A的文件处理工作流程

★可扩展性

我们需要对元数据数据库进行分区,以便可以存储约100万用户和数十亿个文件/块的信息。我们可以对数据进行分区,以在服务器上分配读写请求。

元数据分区:

  1. 我们可以基于文件路径的首字母将文件块存储在分区中。例如,我们将所有以字母“ A”开头的文件保留在一个分区中,并将所有以字母“ B”开头的文件保留在另一个分区中,依此类推。这称为基于范围的分区。不太频繁出现的字母(例如“ Z”或“ Y”),我们可以将它们组合成一个分区。
    主要问题是,某些字母在首字母的情况下很常见。例如,如果我们将所有以字母“ A”开头的文件放入一个数据库分区中,而我们有太多以字母“ A”开头的文件,那么我们就无法将它们放入一个数据库分区中。
  2. 我们也可以基于文件’fileId’的哈希值进行分区。我们的哈希函数将随机生成一个服务器号,并将文件存储在该服务器中。 但是我们可能需要要求所有服务器找到列表,然后将它们合并在一起以得到结果。因此,响应时间延迟可能会增加。
    如果我们使用这种方法,它仍然会导致分区过载,这可以通过使用“一致性哈希”来解决。

缓存:

众所周知,缓存是提高性能的常用技术。这对于降低延迟非常有帮助。服务器可以在访问数据库之前检查缓存服务器,以查看搜索列表是否已在缓存中。我们不能将所有数据都保存在缓存中。

当缓存已满时,我们需要用一个更新的块替换一个块。Least Recently Used(LRU)可以用于此系统。在这种方法中,首先从高速缓存中删除最近最少使用的块。

★安全性:

在文件共享服务中,用户数据的私密性和安全性至关重要。为了解决这个问题,我们可以将每个文件的权限存储在元数据数据库中,哪些文件可由哪个用户查看或修改。

★客户端:

客户端应用程序(Web或移动设备)传输用户上传到云存储中的所有文件。该应用程序将上传,下载或修改文件到云存储。客户端可以更新元数据,例如重命名文件名,编辑文件等。

客户端应用程序功能包括上传,下载文件。如上所述,我们将每个文件分成2MB的较小块,以便仅传输修改后的块,而不传输整个文件。

如果由于用户的离线状态而引起任何冲突,则应用需要对其进行处理。现在,我们可以在客户端保留元数据的本地副本,以使我们能够进行脱机更新。

客户端应用程序需要检测客户端文件夹中的文件是否已更改。我们可能有一个组件Watcher。它将检查客户端是否发生任何文件更改。

★客户如何知道云存储已完成更改?

客户端可以定期与服务器核对是否有任何更改,这是一项手动策略。但是,如果客户端经常检查服务器的更改,则会给服务器带来压力,使服务器繁忙。

我们可以使用HTTP 长时间轮询 技术。 在这种技术中,服务器不会立即响应客户端请求。服务器不发送空响应,而是使请求保持打开状态。 一旦准备好新信息,服务器就会向客户端发送响应。

在这里插入图片描述
图:客户端应用程序向元数据服务器请求更新元数据信息

我们可以将客户端应用程序分为以下几部分:

  1. 本地数据库将跟踪客户端系统中的所有文件,块,目录路径等。
  2. 块控制器会将文件分割成较小的部分。它还将负责从其块中重建整个文件。这部分将有助于确定文件的最新修改块。而且仅将文件的已修改块发送到服务器,这将节省带宽和服务器计算时间。
  3. 守望者会观察客户端文件夹,如果用户发生任何变化,它会通知索引控制器对用户的作用。它还将监视由同步服务广播的其他客户端(设备)上是否发生了任何更改。
  4. 索引控制器将处理从观察程序收到的事件,并更新有关已修改文件块信息的本地数据库。它将与元数据服务通信,以将更改传送到其他设备并更新元数据数据库。该请求将通过消息请求队列发送到元数据服务。
    下面是系统的完整图:
    在这里插入图片描述

图:Google驱动器的系统设计

★结论:

在此系统中,我们未考虑UI部分。系统中也未考虑更新和脱机编辑的历史记录。移动客户端可以按需同步以节省用户的带宽和空间。在这里,我们没有使用其他服务器进行同步。元数据服务器正在执行该任务。

我们决定将文件分成较小的块,以节省存储空间,带宽使用并减少延迟。 我们添加了Loadbalancer,以在后端服务器之间平均分配传入请求。如果服务器停止工作了,则LB将停止向其发送任何请求。

在云架构中,用户数据的隐私和安全性至关重要。我们可以将每个文件的权限存储在元数据数据库中,以检查哪些文件对哪个用户可见或可以修改。

参见原文.

Charles @ Shenzhen,

2020-sep-23

猜你喜欢

转载自blog.csdn.net/MrCharles/article/details/108761863
今日推荐