SeaweedFS 是一个独立的 Apache 许可的开源项目,其持续开发的实现完全归功于这些出色支持者的支持。如果您想让 SeaweedFS 变得更加强大,请考虑加入我们的 Patreon 赞助商。
我和其他支持者将非常感谢您的支持!
docker run -p 8333:8333 chrislusf/seaweedfs server -s3
weed
或weed.exe
。或者运行go install github.com/seaweedfs/seaweedfs/weed@latest
。weed server -dir=/some/data/dir -s3
以启动一台主服务器、一台卷服务器、一台文件管理器和一台 S3 网关。另外,要增加容量,只需在本地、或在不同weed volume -dir="/some/data/dir2" -mserver="<master_host>:9333" -port=8081
计算机上或在数千台机器。就是这样!
SeaweedFS 是一个简单且高度可扩展的分布式文件系统。有两个目标:
SeaweedFS 最初是作为一个对象存储来有效处理小文件的。中央主机不管理中央主机中的所有文件元数据,而是仅管理卷服务器上的卷,而这些卷服务器管理文件及其元数据。这减轻了中央主服务器的并发压力,并将文件元数据分散到卷服务器中,从而允许更快的文件访问(O(1),通常只需一次磁盘读取操作)。
每个文件的元数据仅需要 40 字节的磁盘存储开销。 O(1) 磁盘读取非常简单,欢迎您用实际用例来挑战性能。
SeaweedFS 首先实现了 Facebook 的 Haystack 设计论文。此外,SeaweedFS 还借鉴了 f4(Facebook 的 Warm BLOB 存储系统)的思想实现了纠删码,与 Facebook 的 Tectonic Filesystem 有很多相似之处
在对象存储之上,可选的 Filer 可以支持目录和 POSIX 属性。 Filer 是一个独立的线性可扩展无状态服务器,具有可定制的元数据存储,例如 MySql、Postgres、Redis、Cassandra、HBase、Mongodb、Elastic Search、LevelDB、RocksDB、Sqlite、MemSql、TiDB、Etcd、CockroachDB、YDB 等。
对于任何分布式键值存储,可以将大值卸载到 SeaweedFS。 SeaweedFS 具有快速的访问速度和线性可扩展的容量,可以作为分布式 Key-Large-Value 存储。
SeaweedFS 可以透明地与云集成。热数据位于本地集群,温数据位于云上,访问时间为 O(1),SeaweedFS 可以实现快速的本地访问时间和弹性的云存储容量。更重要的是,云存储访问API成本被最小化。比直接云存储更快、更便宜!
返回目录
返回目录
返回目录
默认情况下,主节点运行在端口 9333 上,卷节点运行在端口 8080 上。让我们启动一个主节点,在端口 8080 和 8081 上启动两个卷节点。理想情况下,它们应该从不同的机器启动。我们将使用 localhost 作为示例。
SeaweedFS 使用 HTTP REST 操作来读取、写入和删除。响应采用 JSON 或 JSONP 格式。
> ./weed master
> weed volume -dir="/tmp/data1" -max=5 -mserver="localhost:9333" -port=8080 &
> weed volume -dir="/tmp/data2" -max=10 -mserver="localhost:9333" -port=8081 &
要上传文件:首先,向/dir/assign
发送 HTTP POST、PUT 或 GET 请求以获取fid
和卷服务器 URL:
> curl http://localhost:9333/dir/assign
{"count":1,"fid":"3,01637037d6","url":"127.0.0.1:8080","publicUrl":"localhost:8080"}
其次,要存储文件内容,请从响应中向url + '/' + fid
发送 HTTP 多部分 POST 请求:
> curl -F file=@/home/chris/myphoto.jpg http://127.0.0.1:8080/3,01637037d6
{"name":"myphoto.jpg","size":43234,"eTag":"1cc0118e"}
要更新,请发送另一个包含更新的文件内容的 POST 请求。
要删除,请向相同的url + '/' + fid
URL 发送 HTTP DELETE 请求:
> curl -X DELETE http://127.0.0.1:8080/3,01637037d6
现在,您可以将fid
(本例中为 3,01637037d6)保存到数据库字段。
开头的数字 3 代表卷 ID。逗号后面是一个文件密钥 01 和一个文件 cookie 637037d6。
卷 ID 是一个无符号 32 位整数。文件密钥是一个无符号 64 位整数。文件cookie是一个无符号的32位整数,用于防止URL猜测。
文件密钥和文件 cookie 均以十六进制编码。您可以以您自己的格式存储 <volume id, file key, file cookie> 元组,或者简单地将fid
存储为字符串。
如果存储为字符串,理论上需要 8+1+16+8=33 个字节。一个 char(33) 就足够了,因为大多数用途不需要 2^32 卷。
如果空间确实是一个问题,您可以以您自己的格式存储文件 ID。您需要一个 4 字节整数作为卷 id,一个 8 字节长数字作为文件密钥,以及一个 4 字节整数作为文件 cookie。所以16个字节就足够了。
以下是如何呈现 URL 的示例。
首先通过文件的volumeId查找卷服务器的URL:
> curl http://localhost:9333/dir/lookup?volumeId=3
{"volumeId":"3","locations":[{"publicUrl":"localhost:8080","url":"localhost:8080"}]}
由于(通常)没有太多卷服务器,并且卷不经常移动,因此您可以在大多数情况下缓存结果。根据复制类型,一个卷可以有多个副本位置。只需随机选择一个位置进行阅读即可。
现在您可以获取公共 URL、渲染 URL 或通过 URL 直接从卷服务器读取:
http://localhost:8080/3,01637037d6.jpg
请注意,我们在此处添加了文件扩展名“.jpg”。它是可选的,并且只是客户端指定文件内容类型的一种方式。
如果您想要更好的 URL,可以使用以下替代 URL 格式之一:
http://localhost:8080/3/01637037d6/my_preferred_name.jpg
http://localhost:8080/3/01637037d6.jpg
http://localhost:8080/3,01637037d6.jpg
http://localhost:8080/3/01637037d6
http://localhost:8080/3,01637037d6
如果你想获得图像的缩放版本,你可以添加一些参数:
http://localhost:8080/3/01637037d6.jpg?height=200&width=200
http://localhost:8080/3/01637037d6.jpg?height=200&width=200&mode=fit
http://localhost:8080/3/01637037d6.jpg?height=200&width=200&mode=fill
SeaweedFS 在卷级别应用复制策略。因此,当您获取文件 ID 时,您可以指定复制策略。例如:
curl http://localhost:9333/dir/assign?replication=001
复制参数选项有:
000: no replication
001: replicate once on the same rack
010: replicate once on a different rack, but same data center
100: replicate once on a different data center
200: replicate twice on two different data center
110: replicate once on a different rack, and once on a different data center
有关复制的更多详细信息可以在 wiki 上找到。
您还可以在启动主服务器时设置默认复制策略。
卷服务器可以使用特定的数据中心名称启动:
weed volume -dir=/tmp/1 -port=8080 -dataCenter=dc1
weed volume -dir=/tmp/2 -port=8081 -dataCenter=dc2
当请求文件密钥时,可选的“dataCenter”参数可以将分配的卷限制到特定的数据中心。例如,这指定分配的卷应限制为“dc1”:
http://localhost:9333/dir/assign?dataCenter=dc1
返回目录
通常分布式文件系统将每个文件分割成块,中央主机保存文件名、块索引到块句柄的映射,以及每个块服务器拥有哪些块。
主要缺点是中央主控无法有效地处理许多小文件,并且由于所有读取请求都需要经过块主控,因此对于许多并发用户来说它可能无法很好地扩展。
SeaweedFS 不管理块,而是管理主服务器中的数据卷。每个数据卷大小为32GB,可容纳大量文件。并且每个存储节点可以有很多数据卷。所以主节点只需要存储有关卷的元数据,这是一个相当小的数据量,并且通常是稳定的。
实际的文件元数据存储在卷服务器上的每个卷中。由于每个卷服务器只管理自己磁盘上的文件元数据,每个文件只有16字节,因此所有文件访问都可以直接从内存中读取文件元数据,只需要一次磁盘操作即可真正读取文件数据。
为了进行比较,请考虑 Linux 中的 xfs inode 结构为 536 字节。
该架构相当简单。实际数据存储在存储节点上的卷中。一台卷服务器可以有多个卷,并且可以通过基本身份验证支持读取和写入访问。
所有卷均由主服务器管理。主服务器包含卷 ID 到卷服务器的映射。这是相当静态的信息,可以轻松缓存。
对于每个写入请求,主服务器还会生成一个文件密钥,它是一个不断增长的 64 位无符号整数。由于写请求通常不像读请求那么频繁,因此一台主服务器应该能够很好地处理并发性。
当客户端发送写请求时,主服务器返回该文件的(卷 ID、文件密钥、文件 cookie、卷节点 URL)。然后,客户端联系卷节点并 POST 文件内容。
当客户端需要基于(卷 id、文件密钥、文件 cookie)读取文件时,它会通过卷 id 向主服务器询问(卷节点 URL、卷节点公共 URL),或者从缓存中检索该文件。然后客户端可以获取内容,或者只是在网页上呈现 URL,让浏览器获取内容。
有关写入-读取过程的详细信息,请参阅示例。
在当前实现中,每个卷可以容纳 32 GB(32GiB 或 8x2^32 字节)。这是因为我们将内容对齐到 8 字节。通过更改 2 行代码,我们可以轻松地将其增加到 64GiB、128GiB 或更多,但代价是由于对齐而浪费了一些填充空间。
可以有 4 GB(4GiB 或 2^32 字节)的卷。因此系统总大小为 8 x 4GiB x 4GiB,即 128 exbibytes(128EiB 或 2^67 字节)。
每个单独的文件大小都受到卷大小的限制。
存储在卷服务器上的所有文件元信息都可以从内存中读取,无需访问磁盘。每个文件仅采用 <64 位密钥、32 位偏移量、32 位大小> 的 16 字节映射条目。当然,每个地图条目都有自己的地图空间成本。但通常磁盘空间先于内存耗尽。
本地卷服务器速度要快得多,而云存储具有弹性容量,如果不经常访问(通常免费上传,但访问成本相对较高),实际上更具成本效益。凭借仅附加结构和 O(1) 访问时间,SeaweedFS 可以通过将热数据卸载到云端来利用本地和云存储。
通常热数据是新鲜的,温数据是旧的。 SeaweedFS 将新创建的卷放在本地服务器上,并可选择将旧卷上传到云上。如果较旧的数据访问频率较低,这实际上可以通过有限的本地服务器为您提供无限的容量,并且对于新数据来说仍然很快。
访问时间为 O(1),网络延迟成本保持在最低水平。
如果热/温数据按照20/80分割,使用20台服务器,可以实现100台服务器的存储容量。这相当于节省了 80% 的成本!或者,您也可以重新调整 80 台服务器的用途来存储新数据,并获得 5 倍的存储吞吐量。
返回目录
大多数其他分布式文件系统似乎比必要的更复杂。
SeaweedFS 的设置和操作都旨在快速且简单。如果你到达这里时还不明白它是如何工作的,我们就失败了!请提出任何问题或更新此文件并进行澄清。
SeaweedFS 不断前进。与其他系统相同。这些比较可能很快就会过时。请帮助保持更新。
返回目录
HDFS对每个文件使用块方法,非常适合存储大文件。
SeaweedFS 非常适合快速并发地处理相对较小的文件。
SeaweedFS 还可以通过将超大文件分割成可管理的数据块来存储超大文件,并将数据块的文件 ID 存储到元块中。这是由“杂草上传/下载”工具管理的,杂草主控或卷服务器对此不可知。
返回目录
这些架构大部分是相同的。 SeaweedFS 旨在通过简单、扁平的架构快速存储和读取文件。主要区别是
系统 | 文件元数据 | 文件内容读取 | POSIX | 休息API | 针对大量小文件进行了优化 |
---|---|---|---|---|---|
海藻FS | 查找卷 ID,可缓存 | O(1) 磁盘寻道 | 是的 | 是的 | |
SeaweedFS 文件管理器 | 可线性扩展、可定制 | O(1) 磁盘寻道 | 保险丝 | 是的 | 是的 |
GlusterFS | 散列 | 保险丝、NFS | |||
头孢 | 哈希+规则 | 保险丝 | 是的 | ||
穆斯FS | 记忆中 | 保险丝 | 不 | ||
最小IO | 每个文件都有单独的元文件 | 是的 | 不 |
返回目录
GlusterFS 将文件(包括目录和内容)存储在称为“bricks”的可配置卷中。
GlusterFS 将路径和文件名散列到 ids 中,并分配给虚拟卷,然后映射到“bricks”。
返回目录
MooseFS选择忽略小文件问题。根据 moosefs 3.0 手册,“即使是一个小文件也会占用 64KiB 加上另外 4KiB 的校验和和 1KiB 的标头”,因为它“最初是为保存大量(如数千个)非常大的文件而设计的”
MooseFS 主服务器将所有元数据保存在内存中。与 HDFS namenode 相同的问题。
返回目录
Ceph 可以像 SeaweedFS 一样设置为 key->blob 存储。它要复杂得多,需要在其之上支持层。这是更详细的比较
SeaweedFS 有一个集中的主组来查找空闲卷,而 Ceph 使用哈希和元数据服务器来定位其对象。拥有集中式主机可以轻松编码和管理。
Ceph 与 SeaweedFS 一样,基于对象存储 RADOS。 Ceph 相当复杂,评论褒贬不一。
Ceph使用CRUSH哈希来自动管理数据放置,可以高效地定位数据。但数据必须按照CRUSH算法来放置。任何错误的配置都会导致数据丢失。拓扑变化,例如添加新服务器以增加容量,将导致高IO成本的数据迁移以适应CRUSH算法。 SeaweedFS 通过将数据分配给任何可写卷来放置数据。如果写入一个卷失败,只需选择另一个卷进行写入。添加更多卷也非常简单。
SeaweedFS 针对小文件进行了优化。小文件存储为一个连续的内容块,文件之间最多有 8 个未使用的字节。小文件访问是 O(1) 磁盘读取。
SeaweedFS Filer 使用现成的存储来管理文件目录,例如 MySql、Postgres、Sqlite、Mongodb、Redis、Elastic Search、Cassandra、HBase、MemSql、TiDB、CockroachCB、Etcd、YDB。这些商店经过验证、可扩展且更易于管理。
海藻FS | 与 Ceph 相当 | 优势 |
---|---|---|
掌握 | MDS | 更简单 |
体积 | 屏幕显示 | 针对小文件进行了优化 |
锉刀 | 头孢FS | 线性可扩展、可定制、O(1) 或 O(logN) |
返回目录
MinIO 紧密遵循 AWS S3,非常适合测试 S3 API。它具有良好的 UI、策略、版本控制等。SeaweedFS 正在努力迎头赶上。也可以稍后将MinIO作为网关放在SeaweedFS前面。
MinIO 元数据位于简单文件中。每个文件写入都会对相应的元文件产生额外的写入。
MinIO 没有针对大量小文件进行优化。文件只是按原样存储到本地磁盘。再加上额外的元文件和纠删码分片,只会加剧 LOSF 问题。
MinIO有多个磁盘IO来读取一个文件。 SeaweedFS 的磁盘读取速度为 O(1),即使对于纠删码文件也是如此。
MinIO 具有全时擦除编码。 SeaweedFS 对热数据使用复制以提高速度,并可选择对热数据应用纠删码。
MinIO 没有类似 POSIX 的 API 支持。
MinIO对存储布局有特定的要求。容量调整不灵活。在 SeaweedFS 中,只需启动一台指向主服务器的卷服务器。就这样。
这是一个超级令人兴奋的项目!我们需要帮助和支持!
返回目录
不熟悉golang的用户安装指南
步骤 1:在您的计算机上安装 go 并按照以下说明设置环境:
https://golang.org/doc/install
确保定义你的 $GOPATH
第 2 步:签出此存储库:
git clone https://github.com/seaweedfs/seaweedfs.git
第三步:执行以下命令下载、编译、安装项目
cd seaweedfs/weed && make install
完成此操作后,您将在$GOPATH/bin
目录中找到可执行文件“weed”
返回目录
在SeaweedFS上测试读取性能时,它基本上变成了对硬盘随机读取速度的性能测试。硬盘通常可达 100MB/s~200MB/s。
要修改或删除小文件,SSD 必须一次删除整个块,并将现有块中的内容移动到新块。全新的 SSD 速度很快,但随着时间的推移会变得碎片化,你必须进行垃圾收集、压缩块。 SeaweedFS 对 SSD 很友好,因为它是仅追加的。删除和压缩是在后台按音量级别完成的,不会减慢读取速度,也不会造成碎片。
返回目录
我自己在带固态盘的Mac Book上得到的不科学的单机结果,CPU:1个Intel Core i7 2.6GHz。
写入100万个1KB文件:
Concurrency Level: 16
Time taken for tests: 66.753 seconds
Completed requests: 1048576
Failed requests: 0
Total transferred: 1106789009 bytes
Requests per second: 15708.23 [#/sec]
Transfer rate: 16191.69 [Kbytes/sec]
Connection Times (ms)
min avg max std
Total: 0.3 1.0 84.3 0.9
Percentage of the requests served within a certain time (ms)
50% 0.8 ms
66% 1.0 ms
75% 1.1 ms
80% 1.2 ms
90% 1.4 ms
95% 1.7 ms
98% 2.1 ms
99% 2.6 ms
100% 84.3 ms
随机读取100万个文件:
Concurrency Level: 16
Time taken for tests: 22.301 seconds
Completed requests: 1048576
Failed requests: 0
Total transferred: 1106812873 bytes
Requests per second: 47019.38 [#/sec]
Transfer rate: 48467.57 [Kbytes/sec]
Connection Times (ms)
min avg max std
Total: 0.0 0.3 54.1 0.2
Percentage of the requests served within a certain time (ms)
50% 0.3 ms
90% 0.4 ms
98% 0.6 ms
99% 0.7 ms
100% 54.1 ms
make benchmark
warp: Benchmark data written to "warp-mixed-2023-10-16[102354]-l70a.csv.zst"
Mixed operations.
Operation: DELETE, 10%, Concurrency: 20, Ran 4m59s.
* Throughput: 6.19 obj/s
Operation: GET, 45%, Concurrency: 20, Ran 5m0s.
* Throughput: 279.85 MiB/s, 27.99 obj/s
Operation: PUT, 15%, Concurrency: 20, Ran 5m0s.
* Throughput: 89.86 MiB/s, 8.99 obj/s
Operation: STAT, 30%, Concurrency: 20, Ran 5m0s.
* Throughput: 18.63 obj/s
Cluster Total: 369.74 MiB/s, 61.79 obj/s, 0 errors over 5m0s.
要查看分段请求统计信息,请使用 --analyze.v 参数。
warp analyze --analyze.v warp-mixed-2023-10-16[102354]-l70a.csv.zst
18642 operations loaded... Done!
Mixed operations.
----------------------------------------
Operation: DELETE - total: 1854, 10.0%, Concurrency: 20, Ran 5m0s, starting 2023-10-16 10:23:57.115 +0500 +05
* Throughput: 6.19 obj/s
Requests considered: 1855:
* Avg: 104ms, 50%: 30ms, 90%: 207ms, 99%: 1.355s, Fastest: 1ms, Slowest: 4.613s, StdDev: 320ms
----------------------------------------
Operation: GET - total: 8388, 45.3%, Size: 10485760 bytes. Concurrency: 20, Ran 5m0s, starting 2023-10-16 10:23:57.12 +0500 +05
* Throughput: 279.77 MiB/s, 27.98 obj/s
Requests considered: 8389:
* Avg: 221ms, 50%: 106ms, 90%: 492ms, 99%: 1.739s, Fastest: 8ms, Slowest: 8.633s, StdDev: 383ms
* TTFB: Avg: 81ms, Best: 2ms, 25th: 24ms, Median: 39ms, 75th: 65ms, 90th: 171ms, 99th: 669ms, Worst: 4.783s StdDev: 163ms
* First Access: Avg: 240ms, 50%: 105ms, 90%: 511ms, 99%: 2.08s, Fastest: 12ms, Slowest: 8.633s, StdDev: 480ms
* First Access TTFB: Avg: 88ms, Best: 2ms, 25th: 24ms, Median: 38ms, 75th: 64ms, 90th: 179ms, 99th: 919ms, Worst: 4.783s StdDev: 199ms
* Last Access: Avg: 219ms, 50%: 106ms, 90%: 463ms, 99%: 1.782s, Fastest: 9ms, Slowest: 8.633s, StdDev: 416ms
* Last Access TTFB: Avg: 81ms, Best: 2ms, 25th: 24ms, Median: 39ms, 75th: 65ms, 90th: 161ms, 99th: 657ms, Worst: 4.783s StdDev: 176ms
----------------------------------------
Operation: PUT - total: 2688, 14.5%, Size: 10485760 bytes. Concurrency: 20, Ran 5m0s, starting 2023-10-16 10:23:57.115 +0500 +05
* Throughput: 89.83 MiB/s, 8.98 obj/s
Requests considered: 2689:
* Avg: 1.165s, 50%: 878ms, 90%: 2.015s, 99%: 5.74s, Fastest: 99ms, Slowest: 8.264s, StdDev: 968ms
----------------------------------------
Operation: STAT - total: 5586, 30.2%, Concurrency: 20, Ran 5m0s, starting 2023-10-16 10:23:57.113 +0500 +05
* Throughput: 18.63 obj/s
Requests considered: 5587:
* Avg: 15ms, 50%: 11ms, 90%: 34ms, 99%: 80ms, Fastest: 0s, Slowest: 245ms, StdDev: 17ms
* First Access: Avg: 14ms, 50%: 10ms, 90%: 33ms, 99%: 69ms, Fastest: 0s, Slowest: 203ms, StdDev: 16ms
* Last Access: Avg: 15ms, 50%: 11ms, 90%: 34ms, 99%: 74ms, Fastest: 0s, Slowest: 203ms, StdDev: 17ms
Cluster Total: 369.64 MiB/s, 61.77 obj/s, 0 errors over 5m0s.
Total Errors:0.
返回目录
根据 Apache 许可证 2.0 版(“许可证”)获得许可;除非遵守许可证,否则您不得使用此文件。您可以在以下位置获取许可证副本:
http://www.apache.org/licenses/LICENSE-2.0
除非适用法律要求或书面同意,否则根据许可证分发的软件均按“原样”分发,不带任何明示或暗示的保证或条件。请参阅许可证,了解许可证下管理权限和限制的特定语言。
本页的文本可根据 Creative Commons Attribution-Sharealike 3.0 Unported License 和 GNU Free Documentation License(无版本,没有不变部分、封面文本或封底文本)的条款进行修改和重复使用。
返回目录