FastDFS详解

1 背景与演进

1.1 为什么需要分布式文件系统

阶段 特点 优缺点
单机时代 项目目录下建立静态文件夹 简单但文件与代码耦合,流量大时影响业务
独立文件服务器 图片服务器 + Nginx 独立部署 性能分离但存在单机瓶颈
分布式文件系统 存储 + 仲裁 + 容灾三系统配合 高可用、可扩展,但复杂度较高

1.2 适用场景

FastDFS 特别适合以中小文件(建议范围:4KB < file_size < 500MB)为载体的在线服务:

  • 相册网站
  • 视频网站
  • 网盘、社区、广告等业务存储

2 FastDFS 概述

2.1 核心特性

  • 轻量级:纯 C 实现,支持 Linux、FreeBSD 等 UNIX 系统
  • 文件一对一:文件不分块存储,与 OS 文件系统一一对应
  • 去重:相同内容文件只保存一份,节约磁盘空间
  • HTTP 支持:内置 Web Server 或配合 Nginx/Apache
  • 在线扩容:支持动态扩展存储容量
  • 主从文件:支持主从文件机制
  • 高性能:V2.0 采用 libevent 网络通信,支持大并发

2.2 架构定位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
┌─────────────────────────────────────────────────────┐
│ Client │
│ (业务请求发起方) │
└─────────────────────┬───────────────────────────────┘

┌───────▼───────┐
│ Tracker │
│ (调度中心) │
└───────┬───────┘

┌─────────────┼─────────────┐
│ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
│Storage 1│ │Storage 2│ │Storage N│
│ (Group1)│ │ (Group1)│ │ (Group2)│
└─────────┘ └─────────┘ └─────────┘

3 核心概念

3.1 服务角色

角色 职责 特点
Tracker Server 调度、负载均衡 内存记录所有 storage 状态,无持久化,易扩展
Storage Server 文件存储 以组为单位组织,文件属性(meta-data)一并保存
Client 业务请求发起 通过专有 API 与 tracker/storage 交互

3.2 核心术语

术语 说明
Group / Volume 卷/组,同组内服务器文件完全相同,互为备份
Meta-data 文件属性,Key-Value 键值对(如:width=1024)
FID File ID,文件唯一标识

3.3 Storage 组织结构

1
2
3
4
5
6
7
8
9
Storage Server
├── /data/disk1/ # 数据存储目录1
│ ├── 00/
│ │ ├── 00/
│ │ ├── 01/
│ │ └── ...
│ └── FF/
├── /data/disk2/ # 数据存储目录2
└── ...
  • 每个存储目录创建 2 级子目录(每级 256 个)
  • 总共 65536 个文件目录
  • 文件按 hash 路由到对应子目录

4 上传机制

4.1 上传流程

1
2
3
4
5
6
┌──────────┐     ┌──────────┐     ┌──────────┐     ┌──────────┐
│ Client │────▶│ Tracker │────▶│ Storage │────▶│ 写入磁盘 │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
│ │
▼ ▼
返回 ip:port 生成 file_id

4.2 选择策略

1. 选择 Group

规则 说明
Round robin 所有 group 间轮询
Specified group 指定确定 group
Load balance 剩余空间多的 group 优先

2. 选择 Storage Server

规则 说明
Round robin group 内所有 storage 间轮询
First server ordered by IP 按 IP 排序
First server ordered by priority 按优先级排序

3. 选择 Storage Path

规则 说明
Round robin 多个存储目录间轮询
剩余空间优先 剩余存储空间最多的目录优先

4.3 FileId 生成

1
FileId = base64(storage_ip + 文件创建时间 + 文件大小 + crc32 + 随机数)

4.4 文件名组成

1
文件名 = group + 虚拟磁盘路径 + 两级子目录 + file_id + 文件后缀

示例

1
group1/M00/00/00/wKgBaE9u4O6Ab7SDAAvgG5Q3vw428.jpg

5 下载机制

5.1 下载流程

1
2
3
┌──────────┐     ┌──────────┐     ┌──────────┐     ┌──────────┐
│ Client │────▶│ Tracker │────▶│ Storage │────▶│ 返回文件 │
└──────────┘ └──────────┘ └──────────┘ └──────────┘

5.2 Storage 选择策略

Tracker 按以下优先级选择可读的 storage:

优先级 条件 说明
1 源头 storage 文件上传时的源服务器,肯定包含文件
2 同步完成 文件创建时间 + 最大同步时间 < 当前时间
3 同步时间戳 文件创建时间 < storage 同步时间戳
4 延迟阈值 当前时间 - 文件创建时间 > 同步延迟阈值

6 同步机制

6.1 同步原理

1
2
3
4
5
6
┌──────────┐      binlog       ┌──────────┐
│Storage A │ ───────────────▶ │Storage B │
└──────────┐ └──────────┘
│ │
└─────────── 上报 ──────────────┘
Tracker
  • Storage 写文件后,后台异步同步到同组其他 server
  • 同步信息以 binlog 形式记录(不包含文件数据)
  • 同步进度以时间戳方式记录

6.2 时钟同步要求

集群内所有服务器时钟必须保持同步,否则同步进度计算会出错。


7 文件定位(FID)

7.1 FID 组成

1
FID = group + 虚拟磁盘路径 + 两级子目录 + file_id + 文件后缀

7.2 快速定位原理

步骤 操作 说明
1 解析 group tracker 定位到目标 storage group
2 解析路径 根据虚拟磁盘路径定位存储目录
3 解析目录 根据两级子目录定位具体目录
4 查找文件 根据文件名定位文件

8 集群部署

8.1 典型架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
                ┌─────────────────────────────────────┐
│ Nginx │
│ (负载均衡/静态资源) │
└─────────────────┬───────────────────┘

┌──────────────────────────┼──────────────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ Tracker1 │ │ Tracker2 │ │ Tracker3 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
┌──────┴──────┐ ┌──────┴──────┐ ┌──────┴──────┐
│ Group1 │ │ Group2 │ │ Group3 │
│ S1 S2 S3 │ │ S4 S5 S6 │ │ S7 S8 S9 │
└─────────────┘ └─────────────┘ └─────────────┘

8.2 部署建议

配置项 建议
Tracker 数量 至少 2 台,实现高可用
Group 内 Storage 3 台以上,互为备份
存储目录 多磁盘挂载,充分利用空间
时钟同步 所有节点配置 NTP 服务

9 Java 客户端使用

9.1 Maven 依赖

1
2
3
4
5
<dependency>
<groupId>org.csource</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.29-RELEASE</version>
</dependency>

9.2 配置文件

1
2
3
fastdfs.tracker_list=192.168.1.100:22122,192.168.1.101:22122
fastdfs.connect_timeout_in_seconds=5
fastdfs.network_timeout_in_seconds=30

9.3 上传示例

1
2
3
4
5
6
7
8
TrackerClient trackerClient = new TrackerClient();
TrackerServer trackerServer = trackerClient.getConnection();
StorageServer storageServer = null;

StorageClient storageClient = new StorageClient(trackerServer, storageServer);
String[] result = storageClient.upload_file("/path/to/file.jpg", "jpg", null);
System.out.println("Group: " + result[0]);
System.out.println("Path: " + result[1]);

10 总结

10.1 核心优势

  • 高性能:轻量级设计,支持高并发
  • 高可用:多 tracker、多 storage 集群支持
  • 可扩展:在线扩容,灵活增加存储节点
  • 低成本:开源免费,硬件要求低

10.2 适用场景

  • 中小文件为主的在线服务
  • 需要高可用存储的业务系统
  • 对成本敏感但需要分布式存储的场景

10.3 参考资源

资源 链接
官方 GitHub https://github.com/happyfish100/
配置文档 https://github.com/happyfish100/fastdfs/wiki/
Java 客户端 https://github.com/happyfish100/fastdfs-client-java