一、什么是FastDFS
FastDFS(Fast Distributed File System)是一个开源的分布式文件系统,它旨在提供高性能、高可靠性和可扩展性的文件存储解决方案,解决海量数据存储问题。其主要的功能包括:文件存储,同步和访问。特别适合以中小文件(建议范围:4KB < file_size <500MB)为载体的在线服务,如图片分享和视频分享网站。
举个例子,想象你有一个大型的网站,用户可以上传和下载大量的图片和视频文件。如果这些文件都存储在单个服务器上,可能会导致服务器负载过高、存储空间不足以及访问速度慢等问题。这时就需要将这些文件分布式地存储在多台服务器上,以提高整个系统的性能和可靠性。
FastDFS 就是为了解决这个问题而设计的,它可以将大文件切分成小块,并将这些小块分散存储在多个服务器上,实现文件的分布式存储。同时,FastDFS 还提供了文件上传、下载、删除等操作的接口,使得开发人员可以方便地操作这些分布式文件。
二、FastDFS的架构
FastDFS由 跟踪服务器(tracker server)、存储服务器(storage server)和客户端(client) 三个部分组成。
2.1 跟踪服务器(tracker server)
跟踪服务器,主要做调度工作,起负载均衡的作用。在内存中记录集群中所有存储组和存储服务器的状态信息,是客户端和数据服务器交互的枢纽。
Tracker是FastDFS的协调者,主要做调度工作,负责管理所有的storage server和group。
1)每个storage在启动后会连接Tracker,告知自己所属的group等信息,并保持周期性的心跳。tracker根据storage的心跳信息,建立group ==> [storage server list]的映射表。
2)client 访问 storage server 之前,必须先访问 tracker server,动态获取到 storage server 的连接信息,最终数据是和一个可用的 storage server 进行传输。
Tracker需要管理的元信息很少,会全部存储在内存中;另外tracker上的元信息都是由storage汇报的信息生成的,本身不需要持久化任何数据,这样使得tracker非常容易扩展,直接增加tracker机器即可扩展为tracker cluster来服务,cluster里每个tracker之间是完全对等的,所有的tracker都接受stroage的心跳信息,生成元数据信息来提供读写服务。
2.2 存储服务器(storage server)
Storage server以组(卷,group或volume)为单位组织,一个group内包含多台storage机器,数据互为备份。存储空间以group内容量最小的storage为准。所以建议group内的多个storage尽量配置相同,以免造成存储空间的浪费。
以group为单位组织存储能方便的进行应用隔离、负载均衡、副本数定制(group内storage server数量即为该group的副本数)。
1)将不同应用数据存到不同的group就能隔离应用数据
2)根据应用的访问特性来将应用分配到不同的group来做负载均衡;
缺点是group的容量受单机存储容量的限制,同时当group内有机器坏掉时,数据恢复只能依赖group内地其他机器,使得恢复时间会很长。
group内每个storage的存储依赖于本地文件系统,storage可配置多个数据存储目录,比如有10块磁盘,分别挂载在/data/disk1 到 /data/disk10,则可将这10个目录都配置为storage的数据存储目录。
storage接受到写文件请求时,会根据配置好的规则,选择其中一个存储目录来存储文件。为了避免单个目录下的文件数太多,在storage第一次启动时,会在每个数据存储目录里创建2级子目录,每级256个,总共65536个文件,新写的文件会以hash的方式被路由到其中某个子目录下,然后将文件数据直接作为一个本地文件存储到该目录中。
这种方式会加快文件索引。
2.3 客户端(client)
FastDFS向使用者提供基本文件访问接口,比如monitor、upload、download、append、delete等,以客户端库的方式提供给用户使用。
三、 FastDFS功能逻辑分析
3.1 upload file(上传文件)原理
1、选择tracker server
当集群中不止一个tracker server时,由于tracker之间是完全对等的关系,客户端在upload文件时可以任意选择一个trakcer。
2、选择存储的group
当tracker接收到upload file的请求时,会为该文件分配一个可以存储该文件的group,支持如下选择group的规则:
1)Round robin,所有的group间轮询
2)Specified group,指定某一个确定的group
3)Load balance,选择最大剩余空 间的组上传文件
3、选择storage server
当选定group后,tracker会在group内选择一个storage server给客户端,支持如下选择storage的规则:
1)Round robin,在group内的所有storage间轮询
2)First server ordered by ip,按ip排序
3)First server ordered by priority,按优先级排序(优先级在storage上配置)
4、选择storage path
当分配好storage server后,客户端将向storage发送写文件请求,storage将会为文件分配一个数据存储目录,支持如下规则:
1)Round robin,多个存储目录间轮询
2)剩余存储空间最多的优先
5、生成Fileid
选定存储目录之后,storage会为文件生一个Fileid,由:storage server ip、文件创建时间、文件大小、文件crc32(文件内容的检验码)和一个随机数(防止生成重名文件)拼接而成,然后将这个二进制串进行base64编码,转换为可打印的字符串。
6、选择两级目录
当选定存储目录之后,storage会为文件分配一个fileid,每个存储目录下有两级256*256的子目录,storage会按文件fileid路由到其中一个子目录,然后将文件以fileid为文件名存储到该子目录下。
7、生成文件名
当文件存储到某个子目录后,即认为该文件存储成功,接下来会为该文件生成一个文件名,文件名由:group、存储目录、两级子目录、fileid、文件后缀名(由客户端指定,主要用于区分文件类型)拼接而成。
3.2 download file(下载文件)逻辑
客户端upload file成功后,会拿到一个storage生成的文件名,接下来客户端根据这个文件名即可访问到该文件。
1、跟upload file一样,在download file时客户端可以选择任意tracker server。
2、clinet发送download请求给某个tracker,必须带上文件名信息,tracke从文件名中解析出文件的group、大小、创建时间等信息,然后为该请求选择一个storage用来服务读请求。
一致性问题
弱一致性:先返回存储结果,再同步,速度快,不可靠
强一致性:先同步,再返回存储结果,速度慢,安全可靠,非商业付费。
FastDFS 是弱一致性,先返回存储结果,再同步。可能发生同一组内的 storage 未同步的情况。
具体来说,由于group内的文件同步是在后台异步进行的,所以有可能出现:在读的时候,文件还没有同步到某些storage server上。为了尽量避免访问到这样的storage,tracker按照如下规则选择group内可读的storage:
1)该文件上传到的源头storage :源头storage只要存活着,肯定包含这个文件,源头的地址被编码在文件名中。
2)根据时间。在同group下,获取最小的一个同步时间点(各个storage在同一时间,同步完成的时间点不一样)。若在最小同步时间点之前的文件,按照用户的规则随意选择一个storage。若在最小同步时间点之后的文件,选择源storage提供给客户端。
四、海量小文件存储
4.1 海量小文件存储的问题
通常我们认为大小在1MB以内的文件称为小文件,百万级数量及以上称为海量,由此量化定义海量小文件问题。 如社交网站、电子商务、广电、网络视频、高性能计算比如
1)Facebook存储了600亿张以上的图片,推出了专门针对海量小图片定制优化的Haystack进行存储。
2)淘宝目前应该是最大C2C电子商务网站,存储超过200亿张图片,平均大小仅为15KB,也推出了针对小文件优化的TFS文件系统存储这些图片,并且进行了开源。
那么海量小文件存储会带来哪些问题呢?
首先我们先了解一下Linux文件存储结构。
Linux自动将硬盘分成两个区域,
1)一个是inode区(inode table),相当于索引,存放inode所包含的信息,即存放的文件信息。
2)一个是bock数据区,存放文件数据。
每个inode节点的大小,一般是128字节或256字节。inode节点的总数,在格式化时就给定,一般是每1KB或每2KB就设置一个inode。
假定在一块1GB的硬盘中,每个inode节点的大小为128字节,每1KB数据就设置一个inode,那么inode table的大小就会达到128MB,占整块硬盘的12.8%。也就是说,inode越多越浪费磁盘资源。
因此,海量小文件主要有2个问题:
1)如果小文件都小于1KB,而系统初始化的时候每个2K设置一个node,则此时一个文件还是至少占用2K的空间,最后导致磁盘空间利用率不高,小于50%。
2)大量的小文件,导致在增加、查找、删除文件的时候需要遍历过多的node节点,影响效率。
4.2 小文件机制配置
对于小文件,FastDFS采用合并存储的方式,合并存储后的文件称为 trunk 文件。
合并文件存储相关的配置都在tracker.conf中。配置完成后,重启tracker和storage server。
支持小文件存储,只需要设置tracker的use_trunk_file=true, store_server=1, 其他保持默认即可,但也要注意slot_max_size 的大小,这样才知道多大的文件触发小文件存储机制。
#是否启用trunk存储,缺省false,需要打开配置 use_trunk_file = true #trunk文件最小分配单元 字节,缺省256,即使上传的文件只有10字节,也会分配这么多空间。 slot_min_size = 256 #trunk内部存储的最大文件,超过该值会被独立存储,默认16M, #超过这个size的文件,不会存储到trunk file中,而是作为一个单独的文件直接存储到文件系统中。 slot_max_size = 1MB #trunk文件大小,默认 64MB,不要配置得过大或者过小,最好不要超过256MB。 trunk_file_size = 64MB