一. 简介
SeaweedFS 是一种分布式存储,其灵感源自 Facebook 的Haystack照片存储系统,旨在通过 O(1) 磁盘查找(从存储读取请求的数据所需的单磁盘读取操作)以可预测的低延迟存储 Blob、对象和文件。
Seaweedfs 如何存储文件
在 SeaweedFS 集群中,文件存储在位于卷服务器中的卷中,而卷只是一个具有预定义大小的大型空文件,用于存储文件。例如,10 GB 卷可以存储 10,000 个平均大小为 1 MB 的文件。
SeaweedFS 试图解决的问题:
- 文件系统 Inode 磁盘大小限制: 因为每个操作系统中的每个文件都必须有元数据(在 Linux 中也称为 inode),其中包括文件名、路径、权限、创建日期、修改日期以及磁盘中的位置。其中一些存储的元数据至关重要,但其他元数据则浪费磁盘空间。在 XFS 或 EXT4 文件系统中,如果启用CRC ,则默认 inode 大小为 512 字节,这意味着每个文件大小将是文件本身的大小加上 512 字节 inode 大小,这包括空文件。例如,存储 100 万个小文件仅索引节点就需要 512 MB 的额外存储空间。但是,Seaweedfs 通过将多个文件存储在一个较大的文件(卷)中解决了这个问题。此外,在seaweedfs配置中,默认卷大小为30 GB,这意味着所有所需的元数据仅为512字节加上每个文件的16字节(16字节用于卷中的文件元数据,如文件偏移位置和大小)存储在体积。因此,存储100万个小文件只需花费512字节+(100万*16字节),大约等于16MB。对于 Facebook 存储超过 2600 亿张上传图像的情况来说,这种方法很有帮助。
- 从磁盘读取文件所需的磁盘操作: 在包括 XFS 和 EXT4 在内的典型文件系统中,从磁盘读取单个文件需要 3 次或更多磁盘读取操作,一次用于文件路径到 inode 编号的映射,一次用于 inode 映射从磁盘检索到内存,以及从磁盘检索文件的一次操作。Seaweedfs 可以通过将文件的元数据存储在内存中来克服这个问题,因此只对磁盘进行一次读取操作,因为内存访问时间以纳秒为单位,而 HDD 硬盘驱动器以毫秒为单位。
Seaweedfs 集群组件:
典型的 Seaweedfs 集群由以下组件组成:
- 主服务: 在其他分布式文件系统中,主服务器管理存储在存储服务器(卷服务器)中的文件,但在 SeaweedFS 中,主服务器仅管理存储在卷服务器中的卷,而卷服务器将管理存储在卷中的文件。这意味着主服务器将仅存储有关卷的元数据(例如卷大小、卷存储在哪个卷服务器中等)。但是,存储实际文件元数据是卷服务器的职责,而不是主服务器的职责。此外,主服务器还负责选择哪个卷服务器将用于存储新文件以及我们可以从哪个卷服务器访问存储的文件。此外,一旦卷达到最大大小,主服务器将负责将卷转换为只读。
- 卷服务: 卷服务器存储一堆卷,每个卷大小为 30GB(可配置)。卷服务负责在卷中有效存储许多对象(文件和文件块)。此外,将每个文件元数据(文件名、大小、卷上的偏移位置等)存储在磁盘上并将它们缓存在内存中,以提供对它们的快速访问并提供 O(1) 磁盘读取操作。当主节点被选为集群中的领导者时,所有卷服务器都会将每个存储卷的元数据发送给新当选的主节点。
- Filer 服务: 与主服务器和卷服务器交互以上传和下载文件可能是一项繁琐的任务,因此 Seaweedfs 团队创建了 Filer 服务来提供以下功能:
- 连接到主服务器以获取最新的卷位置,并在文件写入期间请求卷服务器 IP、卷 ID 和文件 ID。
- 处理文件和目录操作,例如创建、删除、读取、写入和重命名。
- 跟踪文件和目录的元数据,例如文件 ID、文件大小、上次修改时间和访问时间等......
- 与主服务器通信以跟踪集群状态。
- 记录和审核文件和目录操作。
此外,它还提供了以不同方式访问数据的入口点,其中一些方式是:
- 用于上传和下载文件的 HTTP 入口点。
- 通过 FUSE 挂载点直接将文件读写为本地目录。
- S3 兼容 API。
- 访问来自 Hadoop/Spark/Flink/等的文件。
- 网络DAV。
- Kubernetes CSI 驱动程序。
-
Filer Store Service: 这是一个重要组件,Filer 服务使用它来存储文件元数据(如卷 ID、文件 ID 等)。此外,文件管理器存储还用于扩展文件管理器服务。有两种类型的文件管理器存储
-
共享:所有文件管理器都将与共享文件管理器存储(如 MariaDB、Redis、Cassandra 等)通信。因此,此选项将减轻文件管理器服务器的可扩展性,因为所有文件管理器将使用相同的共享数据库。
-
嵌入式:每个文件管理器都将使用 LevelDB 在本地存储元数据,LevelDB 是 Google 设计的"磁盘中带有内存缓存的键值存储"。在嵌入式文件管理器存储中,所有元数据更改都会传播到所有其他文件管理器(如果存在)。这将确保所有文件管理器都更新为最新的元数据更改。
-
S3服务: 这是一项可选服务,提供以AWS风格设计的S3存储桶。它可以单独启动或与文件管理器同时启动。
下图将显示集群组件和连接 注意:客户端和卷服务器之间的连接是可选的。但是,当客户端使用 Fuse 挂载来挂载集群时,可以使用它。
二. 读写文件的过程
在 Seaweedfs 中,可以采用两种不同的方法来读取或写入文件到集群:
A. 在不使用 Filer 服务的情况下向 Seaweedfs 写入和读取文件
要写入文件,需要执行以下步骤:
- 客户端需要询问主服务器知道哪个卷服务器可用于存储文件,如以下对主服务器的 API 请求所示。
json
curl http://MasterIP:9333/dir/assign
Response: {"fid":"7,016bad1bc0","url":"VolumerServerIP:8080"}"fid":"7,016bad1bc0","url":"VolumerServerIP:8080"}
- 然后客户端可以使用以下请求将文件上传到该卷服务器
css
Curl -F file=@/file.txt http://VolumeServerIP:8080/7,016bad1bc0
文件上传成功后,客户端需要将上传的文件名、卷 ID 和文件 ID(在我们的例子中为 file.txt, 7, 016bad1bc0)存储在数据库中,以便将来读取要求。
以下步骤可用于访问集群中存储的文件:
- 客户端需要查询数据库来获取所请求文件的卷ID、文件ID。在我们的示例中,file.txt 返回的数据应为 (7,016bad1bc0),其中 7 是卷 ID,016bad1bc0 是文件 ID。
- 客户端需要向主节点发送 get 请求,以了解卷 7 存在于哪个卷服务器中,因为卷可能会在卷服务器之间迁移。
json
curl http://MasterIP:9333/dir/lookup?volumeId=7
Response: {"volumeId":"7","locations":[{"url":"VolumeServerIP:8080"}]}"volumeId":"7","locations":[{"url":"VolumeServerIP:8080"}]}
- 然后向卷发出最终的 get 请求以获取文件
ruby
curl http://VolumeServerIP:8080/7,016bad1bc0//VolumeServerIP:8080/7,016bad1bc0
为了简化集群中存储和检索文件的过程,seaweed 团队创建了两项服务:文件存储和文件管理器存储。
B. 使用 Filer 服务向 Seaweedfs 写入和读取文件
如前所述,文件管理器服务为集群提供了不同的入口点,其中之一是文件管理器 Web UI,它允许我们通过 Web 下载或上传文件。下面描述写入新文件的过程:
- 客户端使用 Web UI 将文件上传到文件管理器。
- filer 会要求 master 提供卷服务器 IP、卷 ID 和文件 ID,以将文件存储在卷服务器中。但是,根据文件管理器配置,文件可能会被分成块并作为单独的文件存储在卷服务器中,以提高读写速度。
- 文件管理器会将主服务器返回的数据存储在文件管理器存储中,并在使用嵌入式文件管理器方法的情况下同步其他文件管理器节点。
- 文件管理器会将文件上传到卷服务器。
如果从文件管理器 Web UI 访问文件:
- 在 Web UI 中,客户端将按下其中一个文件来下载它。
- 文件管理器将要求文件管理器存储提供所请求文件的卷 ID、文件 ID。
- 文件管理器将从卷服务器中提取文件并将其提供给用户。但是,如果文件被分块,则文件管理器将提取所有块,然后将这些块组合起来形成文件,然后将请求的文件返回给用户。
三. 功能
Seaweedfs 支持多种有趣的功能:
- 动态添加卷服务器: 为了增加集群存储,可以轻松添加新的卷服务器,并立即用于存储新文件。此外,添加更多卷服务器可以提高读写速度。
- Master Failover: Master服务器通过Raft协议进行协调,选举出Leader。领导者接管管理卷的所有工作。所有其他主服务器只是简单地将请求转发给领导者。如果领导者死亡,将选举另一个领导者,然后所有卷服务器将其心跳及其卷的元数据一起发送给新领导者。新任领导人将承担全部责任。在过渡期间,有时新的领导者可能拥有有关所有卷服务器的部分信息。这仅意味着那些尚未检测到的卷服务器将暂时不可写。
- 垃圾收集: 如果您的系统最近进行了大量删除,则删除的文件的磁盘空间将不会立即恢复。卷磁盘利用率由后台清理作业监控。真空作业将使该卷变为只读,并创建一个仅包含现有文件的新卷。
- 复制: 在 Seaweedfs 中,复制由 defaultReplication=ZYX 参数提供,该参数在设置主服务器时使用。三位数字"ZYX"用于定义集群中如何完成复制。因此,Z代表数据中心级复制,Y代表机架级复制,X代表卷服务器级复制,如下所示:
XYZ=000则不进行复制,仅在集群中存储一份。
XYZ=001,然后在同一架上复制一次。
XYZ=010 然后在同一数据中心的不同机架上复制一次。
XYZ=100,然后在不同的数据中心复制一次。
XYZ=200 在另外两个不同的数据中心上复制两次。XYZ
=110 然后在同一数据中心的不同机架上复制一次。
注意:XYZ 的最大允许值为 999。 - 纠删码: 纠删码是一种用于保护数据免遭丢失或损坏的方法。它涉及创建冗余数据,称为原始数据的奇偶校验。这种冗余允许通过使用冗余部分以及剩余的健康数据来恢复丢失或损坏的数据。在 Seaweedfs 中,纠删码操作由 RS(K,N) 公式提供,其中"K"是卷将分割成的分片数量,"N"是奇偶校验分片的数量。例如,seaweedfs 中默认实现的 EC 是 RS(10,4)。因此,30GB的数据量将被编码成14个EC分片,每个分片的大小为3GB(30/10)。Seaweedfs 将尝试将分片存储在卷中,以便提供以下功能:
- 如果服务器数量少于 4 台,EC 可以防止硬盘故障。
- 如果服务器数量等于4,EC可以防止服务器故障。
- 如果机架数量大于 4,EC 可以防止机架故障。
- 使用 TTL 存储文件: Seaweedfs 通过在将数据写入集群后定义 TTL 值来支持文件过期,这在内容缓存的情况下将变得相当重要。但写入后,如果在 TTL 到期之前读取,文件内容将照常返回。但如果在TTL过期后读取,会报文件丢失,然后返回file is not found。
- 数据加密: Seaweedfs 可以使用存储在文件管理器存储中的生成密钥对卷服务器上的数据进行加密。此外,每个文件都使用不同的密钥进行加密。读取加密文件时,文件管理器服务将从卷中获取文件,然后解密并将文件传送给客户端。
- 云驱动: 此功能可以提供将 S3 存储桶挂载到 Seaweedfs 文件系统(使用 filer 服务)并通过 SeaweedFS 访问远程文件的功能。SeaweedFS 实际上缓存来自云端的文件。根据缓存大小,当缓存满时,所有 S3 存储桶文件都可以通过逐出进行缓存。通过回写式缓存机制,所有写入都将完成到缓存,并且缓存将异步上传或更新 S3 存储桶中的文件。由于上传到 Amazon S3 是免费的,因此用户只需为他们使用的存储付费。因此,这将带来以极快的速度访问本地 SeaweedFS 集群以及以零成本上传网络流量近实时备份到 Amazon S3 的优势。
- 存储分类: 由于存储的数据有热、温、冷三种类型,因此相应地放置数据将是经济高效的。SeaweedFS 支持存储分类,您可以将数据放置到可定制的磁盘类型中,并提供将数据移动到的方法不同的层次。
=> NVME => SSD => HDD => Cloud
=> Critical=> Hot =>Warm => Cold
Seaweedfs 使用卷服务器标记来实现此功能,例如,当创建新的卷服务器时,可以传递 --disk 参数设置磁盘标签,如以下命令所示
bash
weed volume -disk=ssd -port=8080 -dir=/dir/
然后客户端可以使用熔断安装来仅安装带有 SSD 或 HDD 标签的卷。因此,关键业务可以使用SSD卷,而较少的关键业务可以使用HDD卷。
10.带有Cloud Tier的分层存储: 此功能将允许seaweedFS将全卷文件移动到云存储提供商,因为云存储是存储热数据的理想场所。其存储具有可扩展性,并且与本地存储服务器相比,成本通常较低。通常,上传到云端是免费的,这使其成为冷数据的理想选择。
11.图像调整大小: Seaweedfs 提供将图像缩放到不同分辨率的功能,如以下对卷服务器的请求所示
ini
curl http://VolumeServerIP:8080/3/01637037d6.jpg?height=200&width=200
curl http://VolumeServerIP:8080/3/01637037d6.jpg?height=200&width=200&mode=fit
curl http://VolumeServerIP:8080/3/01637037d6.jpg?height=200&width=200&mode=fill
结论
SeaweedFS 是一个分布式文件系统,旨在可扩展且易于使用。它基于将文件存储在分布在服务器集群上的块中的想法。这使得它非常具有可扩展性,因为可以将更多服务器添加到集群中以增加容量。SeaweedFS 还具有容错能力,即使集群中的某些服务器发生故障,它也可以继续运行。