漫谈分布式系统(三):再也不怕存不下

1

系列开篇我们说到,分布式系统的初衷,是想要解决两大问题:

  • 存不下

  • 算的慢

今天这篇,我们就一起看下第一点,分布式文件系统是怎样解决存不下的问题的。

首先,思考一个问题:为什么会存不下?

是某一个文件太大了吗?通常不是。现在我们用的服务器,少则几十 GB,多则上百 TB 的硬盘,很少会有一个文件这么大。毕竟一部 720P 的电影才几 GB。

通常是很多个文件累积的总量太大了。

所以很自然的思路就是,以文件为单位,分散放到很多台服务器上去。

但是这个办法还不够好,很容易碰到问题,比如:

  • 数据分布不均衡

文件大小差距会很大,这就导致有些服务器上会存很多数据,还有些则相对较少。

当然,我们可以不要这么笨,分配的时候把当前文件大小和所有服务器上剩余空间做下比较,然后选择最合适的服务器放上去。

但是这样就会导致另一个问题:

  • 空间分配不够灵活

再试想这样一种情况。现在有 2 台机器 A 和 B,分别剩下 200GB 和 100GB 空间,然后来了个 80GB 的文件,很显然应该放到 A 机器上。但是如果这个文件之后又来了个 150GB 的文件呢,就放不下了。

而如果一开始我们能知道后面有个 150GB 的文件要来,那就可以把第一个文件放到 B,第二个文件放到 A。但这是预测未来,做不到的。

这两个问题,本质上都是因为不均衡导致的,这个不均衡体现在服务器剩余空间和待存储的文件大小两方面。

那怎么解决这个不均衡的问题呢?

仍然是系列第一篇里我们提到的分治的思想。

先打散,各自处理完,然后再合并结果。

服务器存储空间不均衡的问题,操作系统早就解决了。大家肯定都听说过 block 或者 page,我们去读写文件的时候,操作系统都是以这样的固定大小去处理的。

而待存储的文件大小不均衡,就需要应用层自己去处理了。

既然不均衡是由于文件大小不一致导致的,那就强制让它一致起来。把文件拆成若干个同样大小的单元,然后把这些单元分散存储到不同的服务器上去,需要访问文件的时候,再去各个服务器上拿过来合在一起。

这样,以固定大小的单元,而不是文件为单位去存储文件,理论上,只要硬件资源足够,存不下的问题就很好的解决了(当然只解决了最基本的问题,还会很多其他难题,后续的文章会一一说到)。

2

HDFS 就是按照这个思路去做的。

  • 固定大小的单元叫做 block

  • 存储这些 blcok 并提供读写功能的服务叫做 DataNode

  • 一个文件由哪些 block 组成,又存储哪些服务器上,这个信息叫做元数据

  • 存储这些元数据并提供读写操作的服务叫做 NameNode

简化后的结构如下图所示:

3

下面看下写数据的过程是怎样的。

当然,这里我们看的也只是简化后的流程:

  1. Client 找 NameNode 申请,我现在要写一个文件。NameNode 做完诸如权限检查之类的前置工作后,告诉 Client,可以的我准备好了。

  2. Client 收到 NameNode 的确认请求后,进入一个循环,直至数据写完:

    1. 向 NameNode 申请一个 block,NameNode 根据一定规则选出合适的 DataNode 后,告诉 Client

    2. Client 向 NameNode 指定的 DataNode 发送数据,DataNode 接受数据并写到本地

4

再来看看读数据的过程。

同样,是简化后的过程:

  1. Client 像 NameNode 询问,我要读一个文件,告诉我它在哪里。NameNode 做完诸如权限检验之类的检查后,返回对应文件的元信息,一共有哪些 block,分别保存在哪些 DataNode 上。

  2. Client 接收到文件元信息后,去对应的 DataNode 请求对应的 block 数据,最后拼在一起就是完整的文件内容。

5

试想一个图书馆的场景。

馆里新进了一批书,就需要先到管理员(一个人或者一个系统)那里登记,管理员会分配应该放到哪一个书柜上。

用户要借书,也需要到管理员那里询问,管理员告诉他这本书在哪个书柜,用户就能很快找到。

如果新买的书没地方放了,只需要买几个书柜,然后在管理员那里登记下就行。只要有足够的钱买书柜,就不用担心书没地方放。

很容易理解,NameNode 就充当了类似图书馆管理员的角色,而 DataNode 就是书架。

很容易看到,无论是写,还是读,这样的设计都足够简单而有效。

当然,这篇文章只解决了最基础的问题。在一切顺利的理想情况下,我们不用再担心新书没地方放了。

但现实情况总是不理想的。

比如,如果管理员生病(管理系统宕机)了呢?

如果有个书柜年久失修垮掉了呢?

这些问题,在后续的文章里面,都会一一讲到。请大家扫码关注公众号,不要错过。

TL;DR

  • 数据存不下通常都是文件总空间太大,而不是个别文件太大。

  • 以文件为单位分散存储可以一定程度解决存不下,但由于文件大小的不均衡,很快会遇到瓶颈。

  • 经典的分治法可以很好的解决不均衡的问题,大小不一样的文件都拆分成一样大的单元,再以单元为单位分散出去。

  • HDFS 以 block 为单位拆分文件,DataNode 负责提供 block 的读写,NameNode 负责保存文件和 block 的对应关系,block 和机器的对应关系等元信息。

  • 所有对文件的读和写操作,都先经过 NameNode 处理元数据,再和对应的 DataNode 发生具体的数据交换。

存的下还不够,还要存的好。毕竟,海量数据带来的就是海量的成本。下一篇,我们就一起看下海量数据的存储治理。

虽然很忙,但这个系列我一定会坚持写完。请大家关注公众号,点右下角的在看,分享到朋友圈,这些都是对我莫大的鼓励。