分布式文件系统 FastDFS 入门与集群部署实战

在大数据与云计算飞速发展的今天,海量非结构化数据(如图片、视频、文档)的存储与管理成为企业面临的重大挑战。传统单机存储方案受限于容量、性能和可靠性,已难以满足高并发、高可用和横向扩展的需求。FastDFS 作为一款开源的轻量级分布式文件系统,凭借其简洁高效的设计、良好的横向扩展能力及低成本的实现方案,成为中小型企业构建私有云存储或处理海量文件场景的优选方案


一、FastDFS 介绍

FastDFS 是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等。

FastDFS 为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用 FastDFS 很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。

补充知识点:FastDFS 适用场景与局限性

  • 适用场景:中小规模(百 GB 级~数 TB 级)的图片 / 视频 / 附件存储,中小互联网业务的静态资源托管,对成本敏感、追求快速部署的私有云存储场景。
  • 局限性
    • 不支持 POSIX 文件系统接口,只能通过专用 API 或 HTTP 访问;
    • 不支持随机写入,仅支持追加 / 覆盖式修改;
    • 不支持快照、复杂权限控制等高级特性;
    • 大规模集群(千台以上节点)下的运维复杂度较高。

二、FastDFS 核心原理

FastDFS 是一个开源的轻量级分布式文件系统,纯 C 语言实现,目前提供了 C、Java 和 PHP API。功能包括:文件存储,文件同步,文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以中小文件(建议范围:4KB < file_size <500MB)为载体的在线服务。

FastDFS 系统有三个核心角色:跟踪服务器(Tracker Server)存储服务器(Storage Server)客户端(Client)。客户端请求 Tracker 服务器进行文件上传、下载,通过 Tracker 服务器调度最终由 Storage 服务器完成文件上传和下载,在底层存储上通过逻辑的分组概念,使得通过在同组内配置多个 Storage,从而实现软 RAID10。

1. FastDFS 架构详解

1.1 Tracker Server(跟踪服务器)

跟踪服务器,主要做调度工作,起到负载均衡的作用;负责管理所有的 Storage Server 和 Group(存储组)。

每个 Storage 在启动后会连接 Tracker,告知自己所属 Group 等信息,并保持周期性心跳。Tracker 上的元信息都是由 Storage 汇报的信息生成的,本身不需要持久化任何数据,这样使得 Tracker 非常容易扩展,直接增加 Tracker 机器即可扩展为 Tracker Cluster 服务,Cluster 里每个 Tracker 之间是完全对等的,所有的 Tracker 都接受 Storage 的心跳信息,生成元数据信息来提供读写服务,Tracker 根据 Storage 的心跳信息,建立 group => [storage server list] 的映射表。

1.2 Storage Server(存储服务器)

存储服务器,主要提供容量和备份服务:以 Group 为单位,每个 Group 内部可以有多台 Storage Server,数据互为备份。客户端上传的文件最终存储在 Storage 服务器上,Storage Server 没有实现自己的文件系统,而是利用操作系统的文件系统来管理文件,可以将 Storage 称为存储服务器。Storage 可配置多个数据存储目录,比如有 10 块磁盘,分别挂载在 /data/disk1~/data/disk10,则可将这 10 个目录都配置为 Storage 的数据存储目录。

1.3 Client(客户端)

客户端,即上传下载数据的服务器,也就是我们自己的项目所部署在的服务器。FastDFS 向使用者提供基本文件访问接口,比如 uploaddownloadappenddelete 等,以客户端库的方式提供给用户使用。


2. 文件上传流程详解

FastDFS 文件上传的核心流程如下:

  1. 客户端选择 Tracker Server:当集群中不止一个 Tracker 服务器时,由于 Tracker 之间是完全对等的关系,客户端在上传文件时可以任意选择一个 Tracker。
  2. Tracker 分配 Group:当 Tracker 接收到 upload_file 的请求时,会为该文件分配一个可以存储该文件的 Group,支持以下选择规则:
    • Round Robin:所有的 Group 间轮询;
    • Specified Group:指定某一个确定的 Group;
    • Load Balance:剩余存储空间多的 Group 优先。
  3. Tracker 分配 Storage Server:当选定 Group 后,Tracker 会在 Group 内选择一个 Storage Server 给客户端,支持以下选择规则:
    • Round Robin:在 Group 内的所有 Storage 间轮询;
    • First server ordered by ip:按 IP 排序;
    • First server ordered by priority:按优先级排序(优先级在 Storage 上配置)。
  4. 客户端写入 Storage Server:当分配好 Storage Server 后,客户端将向 Storage 发送写文件请求,Storage 将会为文件分配一个数据存储目录,支持以下规则:
    • Round Robin:多个存储目录间轮询;
    • 剩余存储空间最多的优先。
  5. 生成 FileId(文件标识):选定存储目录之后,Storage 会为文件生成一个 FileId,由 Storage 服务器 IP、文件创建时间、文件大小、文件 CRC32 和一个随机数拼接而成,然后将这个二进制串进行 Base64 编码,转换为可打印的字符串。选择两级目录:当选定存储目录之后,Storage 会为文件分配一个 FileId,每个存储目录下有两级 256*256 的子目录,Storage 会按文件 FileId 进行两次 Hash,路由到其中一个子目录,然后将文件以 FileId 为文件名存储到该子目录下。
  6. 生成文件名:当文件存储到某个子目录后,即认为该文件存储成功,接下来会为该文件生成一个文件名,文件名由 group、存储目录、两级子目录、fileid、文件后缀名(由客户端指定,主要用于区分文件类型) 拼接而成。

上传成功后,客户端会收到一个完整的文件 ID,格式为 group_name/虚拟磁盘路径/两级目录/FileId,例如:group1/M00/02/44/wKgDrE34E8wAAAAAAAGkEIYJK42378.sh


3. 文件下载流程详解

upload_file 一样,在 download_file 时客户端可以选择任意 Tracker 服务器。Tracker 发送 download 请求给某个 Tracker,必须带上文件信息,Tracker 从文件名中解析出文件的 group、大小、创建时间 等信息,然后为该请求选择一个 Storage 服务器用来读请求。

(1)定位文件

客户端上传文件后,存储服务器将文件 ID 返回给客户端,此文件 ID 用于以后访问该文件的索引信息。文件索引信息包括:组名、虚拟磁盘路径、数据两级目录、文件名。

  • 组名:文件上传后所在的 Storage 组名称,在文件上传成功后由 Storage 服务器返回,需要客户端自行保存。
  • 虚拟磁盘路径:Storage 配置的虚拟路径,与磁盘选项 store_path* 对应。如果配置了 store_path0 则是 M00,如果配置了 store_path1 则是 M01,以此类推。
  • 数据两级目录:Storage 服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据文件。
  • 文件名:与文件上传时不同。是由存储服务器根据特定信息生成,文件名包含:源存储服务器 IP 地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息。
(2)文件定位过程
  1. 通过组名,Tracker 能够快速定位到客户端需要访问的存储服务器组,并选择合适的存储服务器提供客户端访问;
  2. 存储服务器根据 “文件存储虚拟磁盘路径” 和 “数据文件两级目录” 可以很快定位到文件所在目录,并根据文件名找到客户端需要访问的文件。

4. 同步时间管理与数据同步机制

当一个文件上传成功后,客户端马上发起对该文件下载请求(或删除请求)时,Tracker 如何选定一个适用的存储服务器呢?其实每个存储服务器都需要定时将自身的信息上报给 Tracker,这些信息就包括了本地同步时间(即,同步到的最新文件的时间戳)。而 Tracker 根据各个存储服务器的上报情况,就能够知道刚刚上传的文件,在该存储组中是否已完成了同步。

FastDFS 数据同步机制补充

FastDFS 同组内的 Storage 节点之间会自动进行数据同步,核心机制如下:

  • 主动同步:文件上传到主 Storage 后,自动同步到同组其他副本节点;
  • 被动同步:可手动触发同步过程,将文件从主 Storage 同步到其他副本;
  • 异步同步:文件上传后,后台线程异步完成副本同步,不阻塞客户端上传流程;
  • 同步日志(Binlog):每个 Storage 写文件后,同时会写一份 Binlog,Binlog 里不包含文件数据,只包含文件名等元信息,用于后台同步,Storage 会记录向 Group 内其他 Storage 同步的进度,以便重启后能按上次的进度继续同步;进度以时间戳的方式进行记录,所以能保证集群内所有 Server 的时钟保持同步。

Tracker 会根据 Storage 上报的同步时间戳,选择数据最新的节点响应客户端请求,避免用户访问到还未同步完成的文件。


三、FastDFS 集群部署实战

本次部署采用 2 台 Tracker + 2 台 Storage + 1 台 Nginx 代理的架构,所有节点均使用 OpenEuler 24 操作系统,部署前先规划环境:

操作系统 配置 主机名 IP 备注
OpenEuler24 2C4G tracker01 192.168.10.101 跟踪服务器 1
OpenEuler24 2C4G tracker02 192.168.10.102 跟踪服务器 2
OpenEuler24 2C4G storage1 192.168.10.103 存储服务器 1
OpenEuler24 2C4G storage2 192.168.10.104 存储服务器 2
OpenEuler24 2C4G nginx 192.168.10.105 代理服务器

FastDFS 相关软件包下载地址:

  • FastDFS:https://github.com/happyfish100
  • libfastcommon:基础依赖库
  • fastdfs-nginx-module:Nginx 访问 FastDFS 模块
  • nginx-1.19.5:反向代理服务器

1. 基础环境准备(所有节点执行)

1.1 关闭防火墙与 SELinux

bash

运行

# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld

# 关闭内核安全机制
setenforce 0
sed -i "s/^SELINUX=.*/SELINUX=disabled/g" /etc/selinux/config
1.2 安装依赖包

bash

运行

yum -y install zlib-devel gcc* libtool pcre-devel
yum -y install libjpeg libevent

2. 安装 libfastcommon(所有节点执行)

libfastcommon 是 FastDFS 的基础依赖库,必须先安装:

bash

运行

# 解压源码包
tar zxvf libfastcommon-1.0.36.tar.gz
cd libfastcommon-1.0.36

# 编译安装
./make.sh
./make.sh install

# 配置库文件
cd /usr/lib64
ln -s /usr/lib64/libfastcommon.so /usr/lib/libfastcommon.so
cp libfastcommon.so /usr/lib/

3. 安装编译 FastDFS(所有节点执行)

bash

运行

# 解压 FastDFS 源码包
tar zxvf fastdfs-5.11.tar.gz
cd fastdfs-5.11

# 编译安装
./make.sh
./make.sh install

# 复制配置文件模板
cp /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf
cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage.conf
cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf
cp conf/http.conf /etc/fdfs/
cp conf/mime.types /etc/fdfs/

4. 配置 Tracker 服务器(tracker01、tracker02 节点执行)

4.1 修改 Tracker 配置文件

bash

运行

vi /etc/fdfs/tracker.conf

修改以下关键配置:

ini

disabled=false          # 启用配置文件
port=22122              # tracker 服务器端口(默认22122)
base_path=/fastdfs/tracker  # 存储日志和数据的根目录
store_group=group1      # 设置存储组名称(可自定义)
4.2 创建基础目录

bash

运行

mkdir -p /fastdfs/tracker
4.3 启动 Tracker 服务

bash

运行

/etc/init.d/fdfs_trackerd start

# 验证启动状态
ps -ef | grep fdfs_trackerd
补充:Tracker 高可用说明

两台 Tracker 节点完全对等,客户端可同时配置多个 Tracker 地址,实现故障自动切换。Tracker 本身不存储数据,所有元数据均由 Storage 节点上报,因此无需主从复制,直接横向扩展即可。


5. 配置 Storage 服务(storage1、storage2 节点执行)

5.1 修改 Storage 配置文件

bash

运行

vi /etc/fdfs/storage.conf

修改以下关键配置:

ini

disabled=false                      # 启用配置文件
port=23000                          # storage 服务器端口
base_path=/fastdfs/storage          # 数据和日志文件存储目录
store_path0=/fastdfs/storage        # 第一个存储目录(可配置多个 store_path*)
tracker_server=192.168.10.101:22122 # tracker 服务器IP和端口
tracker_server=192.168.10.102:22122 # 配置两个 tracker 实现高可用
group_name=group1                   # 需要和 tracker 中的组名保持一致
http.server_port=8888               # http 访问文件的端口
5.2 创建基础数据目录

bash

运行

mkdir -p /fastdfs/storage
5.3 启动 Storage 服务

bash

运行

/etc/init.d/fdfs_storaged start

# 验证启动状态
ps -ef | grep fdfs_storaged
补充:Storage 节点数据同步说明

同组内的 Storage 节点会自动进行数据同步,无需手动配置。Storage 启动后会向所有 Tracker 节点上报心跳,包含自身状态、剩余空间、同步时间戳等信息,Tracker 会据此维护节点健康状态。


6. 配置 Client 客户端(任意 FastDFS 节点执行)

bash

运行

vi /etc/fdfs/client.conf

修改以下关键配置:

ini

base_path=/fastdfs/tracker
tracker_server=192.168.10.101:22122
tracker_server=192.168.10.102:22122

7. 测试文件上传(任意节点执行)

7.1 上传文件

bash

运行

# 方式1:使用 fdfs_upload_file 命令上传
fdfs_upload_file /etc/fdfs/client.conf logo.jpg

# 方式2:使用 fdfs_test 工具上传
fdfs_test /etc/fdfs/client.conf upload logo.jpg
7.2 查看上传结果

上传成功后会返回文件 ID,例如:group1/M00/00/00/wKgKZ2gaACmAb6raAAFMnKMrMI895.jpg,同时会输出文件访问 URL:http://192.168.10.103/group1/M00/00/00/wKgKZ2gaACmAb6raAAFMnKMrMI895.jpg

7.3 验证文件存储目录

文件实际存储路径为:/fastdfs/storage/data/00/00/wKgKZ2gaACmAb6raAAFMnKMrMI895.jpg,可通过以下命令查看:

bash

运行

ls -lh /fastdfs/storage/data/00/00/

8. 配置 fastdfs-nginx-module 与 Nginx(所有 Storage 节点执行)

FastDFS 通过 Tracker 服务器,将文件放在 Storage 服务器存储,但是同组存储服务器之间需要进入文件复制,有同步延迟的问题。假设 Tracker 服务器将文件上传到了 storage01,上传成功后文件 ID 已经返回给客户端。此时 FastDFS 存储集群机会将这个文件同步到同组存储 storage02,在文件还没有复制完成的情况下,客户端如果用这个文件 ID 在 storage02 上取文件,就会出现文件无法访问的错误。而 fastdfs-nginx-module 可以重定向文件连接到文件上传时的源服务器取文件,避免客户端由于复制延迟导致的文件无法访问错误。

8.1 解压并修改 fastdfs-nginx-module 配置

bash

运行

tar zxvf fastdfs-nginx-module-v1.16.tar.gz
cd fastdfs-nginx-module/src

# 修改 config 文件,指定依赖库路径
vi config
# 修改以下内容(主要是路径修正)
ngx_addon_name=ngx_http_fastdfs_module
HTTP_MODULES="$HTTP_MODULES ngx_http_fastdfs_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_fastdfs_module.c"
CORE_INCS="$CORE_INCS /usr/include/fastdfs /usr/include/fastcommon/"
CORE_LIBS="$CORE_LIBS -L/usr/lib -lfastcommon -lfdfsclient"
CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=64 -DFDFS_OUTPUT_CHUNK_SIZE=256*1024 -DFDFS_MOD_CONF_FILENAME=\"/etc/fdfs/mod_fastdfs.conf\""
8.2 复制模块配置文件

bash

运行

cp /root/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs/
vi /etc/fdfs/mod_fastdfs.conf

修改关键配置:

ini

connect_timeout=10
base_path=/tmp
tracker_server=192.168.10.101:22122
tracker_server=192.168.10.102:22122
url_have_group_name=true  # 表示URL中包含组名称
group_name=group1
storage_server_port=23000
store_path_count=1
store_path0=/fastdfs/storage
8.3 编译安装 Nginx(集成 fastdfs 模块)

bash

运行

# 解压 Nginx 源码包
tar zxvf nginx-1.19.5.tar.gz
cd nginx-1.19.5

# 复制 FastDFS 头文件
cp /usr/include/fastdfs/* /usr/include/
cp /usr/include/fastcommon/* /usr/include/

# 配置 Nginx,添加 fastdfs 模块
./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--add-module=/root/fastdfs-nginx-module/src/

# 编译安装
make && make install

# 创建软链接
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
8.4 配置 Nginx 支持 FastDFS

bash

运行

vi /usr/local/nginx/conf/nginx.conf

http 块中添加以下配置:

nginx

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  localhost;

        location /group1/M00 {
            ngx_fastdfs_module;
        }
    }
}
8.5 启动 Nginx

bash

运行

# 创建 Nginx 用户
useradd nginx -s /sbin/nologin

# 启动 Nginx
nginx

# 验证启动状态
ps -ef | grep nginx

9. 部署 Nginx 代理(代理节点执行)

代理节点的作用是统一入口,将请求转发到后端 Storage 节点,实现负载均衡:

bash

运行

# 安装 Nginx(同步骤8的编译安装方式,无需添加 fastdfs 模块)
tar zxvf nginx-1.19.5.tar.gz
cd nginx-1.19.5
./configure --prefix=/usr/local/nginx --user=nginx --group=nginx
make && make install
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/

# 修改代理配置
vi /usr/local/nginx/conf/nginx.conf

添加 upstream 和 proxy_pass 配置:

nginx

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    upstream storage_server_group1 {
        server 192.168.10.103:80 weight=10;
        server 192.168.10.104:80 weight=10;
    }

    server {
        listen       80;
        server_name  localhost;

        location / {
            proxy_pass http://storage_server_group1;
        }
    }
}

启动代理 Nginx 后,即可通过代理节点 IP 访问文件:

plaintext

http://192.168.10.105/group1/M00/00/00/wKgKZ2gaACmAb6raAAFMnKMrMI895.jpg

四、FastDFS 总结与扩展

通过本文的学习,我们全面认识了 FastDFS 作为轻量级分布式文件系统的技术特点:通过 Tracker Server 调度与 Storage Server 分组存储实现高效负载均衡,支持断点续传、文件同步与高可用容错,尤其适合中小规模非结构化数据存储场景。从环境部署到集群配置,从客户端集成到性能调优,我们实践了 FastDFS 的完整搭建流程,并探讨了其与 Nginx、CDN 等技术结合的优化方案。

尽管 FastDFS 在元数据管理、动态扩容灵活性等方面存在一定局限性,但其低门槛、高性价比的特性仍使其在特定场景中具有强大生命力。希望通过本文的学习,你不仅能掌握 FastDFS 的技术细节,更能领悟分布式系统设计的核心思想,为未来应对更复杂的存储需求积累宝贵经验。


补充知识点:FastDFS 性能优化与运维建议

  1. 存储目录优化:配置多个 store_path,分散磁盘 I/O 压力,避免单盘瓶颈;
  2. 内存与磁盘配置:Tracker 节点建议配置 4G+ 内存,Storage 节点建议使用 SSD 存储热点数据,机械盘存储冷数据;
  3. 监控告警:通过 fdfs_monitor 工具监控集群状态,配置磁盘使用率、节点心跳、同步延迟告警;
  4. 备份策略:同组多副本 + 跨组备份,避免单组故障导致数据丢失;
  5. 限流与缓存:前端搭配 CDN 缓存静态资源,减少回源请求,降低 Storage 节点压力。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐