高效存储数亿个小文件。 自托管解决方案



亲爱的社区,本文将重点关注有效存储和交付数亿个小文件的问题。 在此阶段,提出了针对POSIX兼容文件系统的最终解决方案,该文件系统完全支持锁(包括集群锁,甚至不附带拐杖)。

因此,为此目的,我编写了自己的专用服务器。
在执行此任务的过程中,可以解决主要问题,同时节省磁盘空间和RAM,这是我们的群集文件系统无情地消耗的。 实际上,如此多的文件对任何群集文件系统都是有害的。

这个想法是这样的:

简单来说,小文件是通过服务器上传的,它们直接保存到档案中,也可以从中读取,大文件放在附近。 方案:1个文件夹= 1个档案,总共我们有几百万个带有小文件的档案,而不是几亿个文件。 所有这些都已完全实现,无需任何脚本并将文件折叠到tar / zip存档中。

我会尽力缩短它的长度,如果这个职位空缺,我先致歉。

一切始于这样一个事实:我在世界上找不到合适的服务器可以将通过HTTP协议接收的数据直接保存到存档中,因此普通存档和对象存储库没有固有的缺点。 搜索的原因是一个由10台服务器组成的集群,这些服务器增长到了一个规模庞大的Origin,其中已经积累了2.5亿个小文件,并且增长趋势不会停止。

那些不喜欢阅读文章和少量文档的人会更容易:

在这里这里

更新资料 从docker镜像中删除了nginx。

和docker同时:
docker run -d --restart=always -e bindaddr=127.0.0.1:9699 \ -e host=localhost -e root=/var/storage -v /var/storage:/var/storage --name wzd \ -p 80:9699 eltaline/wzd 

下一个:

更新资料 在版本1.1.0中,HTTPS / POST / IP身份验证方法等已经出现。

如果有很多文件,则需要大量资源,并且,大多数情况下,浪费了一些资源。 例如,当使用群集文件系统(在本例中为MooseFS)时,无论实际大小如何,文件始终至少占用64 KB。 也就是说,对于3、10或30 KB的文件,磁盘上需要64 KB。 如果有25亿个文件,我们将损失2到10 TB。 由于MooseFS本身存在一个限制,因此不可能无限期地创建新文件:每个文件的一个副本不超过10亿个。

随着文件数量的增加,元数据需要大量RAM。 频繁的大型元数据转储也会导致SSD的磨损。

WZD服务器。 我们将光盘排序。

服务器是用Go编写的。 首先,我需要减少文件数量。 怎么做? 由于存档,但在这种情况下无需压缩,因为我的文件是固定的,经过裁剪的图片。 BoltDB进行了救援,但仍然必须消除缺陷,这在文档中得到了反映。

总体而言,就我而言,仅保留了1000万个Bolt档案,而不是十亿个档案的四分之一。 如果我有机会更改填充目录文件的当前结构,则可以减少到约100万个文件。

所有小文件都打包到Bolt归档文件中,自动接收它们所在目录的名称,所有大文件与归档文件并排放置,将它们打包是没有意义的,这是可自定义的。 小-存档,大-保持不变。 服务器可以同时透明地工作。

wZD服务器的体系结构和功能。



该服务器正在运行Linux,BSD,Solaris和OSX。 我仅在Linux下针对AMD64架构进行了测试,但它也应适用于ARM64,PPC64,MIPS64。

主要特点:

  • 多线程;
  • 多服务器,提供容错和负载平衡;
  • 用户或开发人员的最大透明度;
  • 支持的HTTP方法:GET,HEAD,PUT和DELETE;
  • 通过客户端头管理读写行为;
  • 支持可定制的虚拟主机;
  • 支持读/写时的CRC数据完整性;
  • 半动态缓冲器,可最大程度地减少内存消耗并优化网络性能;
  • 延迟数据压缩
  • 此外,还提供了多线程wZA存档器来进行文件迁移,而无需停止服务。

真实经验:

我开发和测试服务器和存档器已经很长时间了,它已经在实时数据上运行了很长时间,现在它可以成功地在一个群集中运行,该群集包括位于单独SATA磁盘上15,000,000个目录中的250,000,000个小文件(图片)。 由10个服务器组成的群集是安装在CDN网络后面的原始服务器。 为了进行维护,使用了2个Nginx服务器+ 2个wZD服务器。

对于那些决定使用此服务器的用户,在适用之前计划目录结构是有意义的。 立即保留服务器未设计为将所有内容推送到1 Bolt归档文件的保留。

性能测试:

归档文件的大小越小,对其执行GET和PUT操作的速度就越快。 比较HTTP客户端写入常规文件和Bolt存档并读取的总时间。 它将工作与文件大小分别为32 KB,256 KB,1024 KB,4096 KB和32768 KB进行比较。

使用Bolt归档文件时,在写入之前以及写入之后都要检查每个文件的数据完整性(使用CRC),即刻进行读取和重新计数,这自然会带来延迟,但是主要是数据安全性。

我在SSD上进行了性能测试,因为在SATA磁盘上的测试没有明显的区别。

更新(v1.1.0),性能提高了5-25%。

根据测试结果的图表:




如您所见,对于较小的文件,已归档文件和未归档文件之间的读写时间差异很小。

通过读写32 MB文件的测试,我们将得到一张完全不同的图片:



读取文件之间的时间差在5到25毫秒之间。 录制时情况更糟,相差约150毫秒。 但是在这种情况下,不需要上传大文件,这根本没有意义,它们可以与存档分开存放。

*从技术上讲,此服务器还可用于需要NoSQL的任务。

使用wZD服务器的基本方法:

下载常规文件:
 curl -X PUT --data-binary @test.jpg http://localhost/test/test.jpg 

将文件上传到Bolt归档文件(如果未超过服务器参数fmaxsize,该参数确定了归档文件中可以包含的最大文件大小,如果超过该参数,文件将照常加载到归档文件旁边):
 curl -X PUT -H "Archive: 1" --data-binary @test.jpg http://localhost/test/test.jpg 

下载文件(如果磁盘上和归档文件中有相同名称的文件,则在下载时,将默认优先级赋予解压缩的文件):
 curl -o test.jpg http://localhost/test/test.jpg 

从Bolt归档文件下载文件(强制):
 curl -o test.jpg -H "FromArchive: 1" http://localhost/test/test.jpg 


其他方法的说明在文档中。

WZD文档
WZA文件

到目前为止,该服务器仅支持HTTP,但尚不支持HTTPS。 也不支持POST方法(尚未确定是否需要该方法)。

凡是研究源代码的人都可以在其中找到一个太妃糖,并不是每个人都喜欢它,但是除了中断处理程序之外,我没有将主代码绑定到Web框架的功能,以便将来我可以将其快速重写为几乎任何引擎。

待办事项:

  • 我们自己的复制器和分发器+ geo的开发,可以在没有群集FS的大型系统中使用(全部用于成人)
  • 完全丢失元数据时完全恢复还原的能力(如果使用分发服务器)
  • 本机协议,可以为各种编程语言使用永久性网络连接和驱动程序
  • 使用NoSQL组件的高级功能
  • Bolt档案中的文件或值以及普通文件的不同类型(gzip,zstd,snappy)的压缩
  • Bolt档案中的文件或值以及普通文件的不同类型的加密
  • 延迟服务器视频转换,包括GPU

就这样,我希望该服务器对某人来说很方便,BSD-3许可证,双重版权,因为不会有我工作的公司,我也不会写服务器。 我是单数的开发人员。 对于发现的错误和功能请求,我将不胜感激。

Source: https://habr.com/ru/post/zh-CN484312/


All Articles