✨FastDFS:高效的分布式文件系统解析与实践✨
官方:FastDFS: FastDFS是一款轻量级的开源分布式文件系统
在当今互联网应用蓬勃发展的时代,文件存储与管理面临着诸多挑战,如大容量存储、负载均衡以及高并发访问等问题。而 FastDFS 作为一款开源的轻量级分布式文件系统,为我们提供了出色的解决方案。今天,就让我们深入了解一下 FastDFS 的原理、特点以及它的实际使用示例。
一、FastDFS 简介
FastDFS 是专门为互联网应用量身定制的分布式文件存储系统,非常适合存储用户图片、视频、文档等各类文件。它充分考虑了冗余备份、负载均衡、线性扩容等机制,着重关注高可用、高性能等关键指标,使用它能够轻松搭建一套高性能的文件服务器集群,对外提供文件上传、下载等服务,并且基于 Docker 还可以快速进行搭建,方便快捷地应用到项目中。
二、FastDFS 的系统角色
FastDFS 系统主要包含三个重要角色:
- 跟踪服务器(Tracker Server):它的核心职责是调度工作,起到均衡负载的作用。负责管理所有的存储服务器(Storage Server)和存储分组(group),每个存储服务器在启动后会主动连接 Tracker,告知自己所属的 group 等相关信息,并保持周期性的心跳检测。Tracker 服务器上的元信息都是由存储服务器汇报的信息生成的,其本身不需要持久化任何数据,所以扩展起来非常容易,只需增加 Tracker 机器就可扩展为 Tracker 集群来提供服务,集群里的每个 Tracker 之间是完全对等的,都能接收存储服务器的心跳信息,生成元数据信息以支持读写服务,并且根据存储服务器的心跳信息,建立 group 到存储服务器列表的映射表。
- 存储服务器(Storage Server):主要是为系统提供容量支持以及备份服务,以 group 为单位进行组织,每个 group 内部可以配置多台存储服务器,它们之间的数据互为备份。客户端上传的文件最终会存储在这些存储服务器上,值得注意的是,存储服务器并没有自己实现独立的文件系统,而是借助操作系统的文件系统来管理文件。例如,若有 10 块磁盘,分别挂载在
/data/disk1 - /data/disk10
,就可以将这 10 个目录都配置为存储服务器的数据存储目录。 - 客户端(Client):也就是我们自己的项目所部署的服务器,它负责向 FastDFS 发起上传、下载等数据操作请求,FastDFS 向使用者提供了诸如 upload、download、append、delete 等基本文件访问接口,以客户端库的方式供用户使用。
三、文件上传流程详解
- 选择 Tracker Server:当集群中有多个 Tracker Server 时,由于它们之间是完全对等且无状态的关系,客户端在上传文件时可以任意选择一个 Tracker Server。
- 选择存储的 Group:当 Tracker Server 接收到上传文件的请求后,会按照一定规则为该文件分配一个可以存储此文件的 group,支持的规则有:
- Round robin(轮询):在所有的 group 间循环分配。
- Specified group(指定分组):可以指定某一个确定的 group 来存储文件。
- Load balance(负载均衡):优先选择剩余存储空间较多的 group 进行存储。
- 选择 Storage Server:在选定 group 后,Tracker Server 会在该 group 内选择一个 Storage Server 提供给客户端,支持以下几种选择规则:
- Round robin(轮询):在 group 内的所有 Storage Server 间进行轮询选择。
- First server ordered by ip(按 IP 排序):按照存储服务器的 IP 地址进行排序来选择。
- First server ordered by priority(按优先级排序):依据在存储服务器上配置的优先级来进行选择。
- 选择 Storage Path:当分配好 Storage Server 后,客户端会向其发送写文件请求,Storage Server 将会按照规则为文件分配一个数据存储目录,例如:
- Round robin(轮询):在多个存储目录之间循环选择。
- 剩余存储空间最多的优先:优先选择剩余空间多的存储目录存放文件。
- 生成 Fileid:选定存储目录之后,Storage Server 会为文件生成一个 Fileid,它由 Storage Server 的 IP 地址、文件创建时间、文件大小、文件 crc32 和一个随机数拼接而成,然后将这个二进制串进行 base64 编码,转换为可打印的字符串。
- 选择两级目录:每个存储目录下设有两级 256 * 256 的子目录,Storage Server 会依据文件的 Fileid 进行两次哈希(猜测),从而路由到其中一个子目录,之后将文件以 Fileid 为文件名存储到该子目录下。
- 生成文件名:当文件成功存储到某个子目录后,就会为该文件生成一个文件名,文件名由 group、存储目录、两级子目录、Fileid、文件后缀名(由客户端指定,用于区分文件类型)等信息拼接而成。
四、文件下载流程
与上传文件类似,在下载文件时客户端同样可以任意选择一个 Tracker Server,然后向其发送带有文件名信息的 download 请求,Tracker Server 从文件名中解析出文件的 group、大小、创建时间等信息,接着为该请求选择一个合适的 Storage Server 来响应读请求,进而实现文件的定位与下载操作。
初始化过程
文件下载过程
五、FastDFS 的优点
- 主备 Tracker 服务:通过设置主备 Tracker 服务,能够显著增强系统的可用性,避免单点故障对整个文件存储服务造成影响。
- 降低系统复杂度:系统不需要支持 POSIX,这使得其内部处理逻辑得以简化,从而提升了处理速度,让文件的存储与访问更加高效。
- 支持主从文件与自定义扩展名:方便用户根据实际需求灵活管理和区分不同类型的文件,增强了文件管理的灵活性。
- 在线扩容机制:具备在线扩容的能力,随着业务的发展和文件数量的增多,可以方便地增加存储服务器等资源,增强了系统的可扩展性,以适应不断变化的业务需求。
- 实现软 RAID:通过软 RAID 机制,有效增强了系统的并发处理能力以及数据容错恢复能力,保障了数据的安全性和系统的稳定性。
六、FastDFS 的缺点
- 存在单点性能瓶颈:目前通过 API 下载文件时,存在单点的性能瓶颈问题,在高并发下载场景下可能会对性能产生一定影响。
- 不支持断点续传:对于大文件的下载来说,如果出现网络中断等情况,无法实现断点续传功能,会给用户带来不便,甚至可能需要重新下载整个文件。
- 同步机制问题:同步机制不支持文件正确性校验,这在一定程度上降低了系统的可用性,可能导致数据不一致等问题出现。
- 通用性较低:不支持 POSIX 通用接口访问,使得其在与一些遵循 POSIX 标准的应用程序或系统集成时存在困难,通用性方面有所欠缺。
- 跨公网同步延迟:在进行跨公网的文件同步时,会存在比较大的延迟,需要应用自身做相应的容错策略来应对这种情况。
七、代码示例
以下是一个使用 FastDFS 进行文件上传、下载、删除以及获取文件 URL 等常用操作的 Java 代码示例,基于 Spring 框架整合 FastDFS 客户端:
package com.zeroone.star.project.components.fastdfs;
import io.github.bluemiaomiao.annotation.EnableFastdfsClient;
import io.github.bluemiaomiao.service.FastdfsClientService;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.File;
@Component
@EnableFastdfsClient
public class FastDfsClientComponent {
@Resource
private FastdfsClientService remoteService;
/**
* 文件上传(指定文件名和扩展名)
*
* @param fileName 文件全路径
* @param extName 文件扩展名,不包含(.)
* @return 上传结果信息
* @throws Exception 存储失败异常
*/
public FastDfsFileInfo uploadFile(String fileName, String extName) throws Exception {
String[] info = remoteService.autoUpload(FileUtils.readFileToByteArray(new File(fileName)), extName);
if (info!= null) {
return FastDfsFileInfo.builder()
.group(info[0])
.storageId(info[1])
.build();
}
return null;
}
/**
* 文件上传(只指定文件名,扩展名自动获取)
*
* @param fileName 文件全路径
* @return 上传结果信息
* @throws Exception 存储失败异常
*/
public FastDfsFileInfo uploadFile(String fileName) throws Exception {
return uploadFile(fileName, null);
}
/**
* 上传文件(指定文件内容字节数组和扩展名)
*
* @param fileContent 文件的内容,字节数组
* @param extName 文件扩展名
* @return 上传结果信息
* @throws Exception 存储失败异常
*/
public FastDfsFileInfo uploadFile(byte[] fileContent, String extName) throws Exception {
String[] info = remoteService.autoUpload(fileContent, extName);
if (info!= null) {
return FastDfsFileInfo.builder()
.group(info[0])
.storageId(info[1])
.build();
}
return null;
}
/**
* 上传文件(只指定文件内容字节数组)
*
* @param fileContent 件的内容,字节数组
* @return 上传结果信息 [0]:服务器分组,[1]:服务器ID
* @throws Exception 存储失败异常
*/
public FastDfsFileInfo uploadFile(byte[] fileContent) throws Exception {
return uploadFile(fileContent, null);
}
/**
* 文件下载
*
* @param info 文件信息
* @return 下载数据
* @throws Exception 异常信息
*/
public byte[] downloadFile(FastDfsFileInfo info) throws Exception {
return remoteService.download(info.getGroup(), info.getStorageId());
}
/**
* 删除文件
*
* @param info 文件信息
* @return 删除结果 0表示删除成功
* @throws Exception 异常信息
*/
public int deleteFile(FastDfsFileInfo info) throws Exception {
return remoteService.delete(info.getGroup(), info.getStorageId());
}
/**
* 解析成url地址
*
* @param info 文件信息
* @param urlPrefix 如:<a href="#">http://ip:port</a>
* @param isToken 是否带防盗链
* @return 获取失败返回null
*/
public String fetchUrl(FastDfsFileInfo info, String urlPrefix, boolean isToken) {
try {
if (isToken) {
return remoteService.autoDownloadWithToken(info.getGroup(), info.getStorageId(), urlPrefix);
} else {
return remoteService.autoDownloadWithoutToken(info.getGroup(), info.getStorageId(), urlPrefix);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
上述代码通过注入FastdfsClientService
,实现了对 FastDFS 中文件的多种操作方法封装,例如:
uploadFile
方法提供了多种重载形式,可以根据文件的路径或者字节数组内容来上传文件到 FastDFS,并返回文件的相关存储信息(如分组和服务器 ID 等)。downloadFile
方法则可以根据文件的存储信息从 FastDFS 中下载文件内容,返回字节数组形式的数据。deleteFile
方法用于删除指定存储信息对应的文件,返回删除结果(0 表示成功)。fetchUrl
方法能够根据文件存储信息以及指定的 URL 前缀等参数,生成可访问文件的 URL 地址,并且支持是否添加防盗链功能。
总之,FastDFS 作为一款功能强大的分布式文件系统,尽管存在一些不足之处,但在适合的应用场景中(如中小文件为主的互联网在线服务),能够凭借其自身优势为我们提供高效可靠的文件存储与管理服务,帮助我们构建稳定的业务系统。
希望通过这篇博客以及代码示例,大家对 FastDFS 有了更清晰的认识和理解,能够在实际项目中更好地运用它。
觉得有用的话可以点点赞 (*/ω\*),支持一下。
如果愿意的话关注一下。会对你有更多的帮助。
每天都会不定时更新哦 >人< 。