分布式文件系统 FastDFS

分布式文件系统 FastDFS

  1. 分布式文件系统应用场景
  2. FastDFS
  3. FastDFS 单机环境搭建
  4. 与 springboot 结合

分布式文件系统应用场景

互联网海量非结构化数据的存储需求

  • 电商网站:海量商品图片
  • 视频网站:海量视频文件
  • 网盘:海量文件
  • 社交网站:海量图片

FastDFS

1、简介

FastDFS 是一个开源的高性能分布式文件系统(DFS),它的主要功能包括:文件存储,文件同步和文件访问,以及高容量和负载平衡。主要解决了海量数据存储问题,特别适合中小文件(建议范围:4kb < file_size < 500 MB)为载体的在线服务

FastDFS 是设计用来存储小文件的,过大的文件处理方案是拆分为小文件,可跟踪小文件的上传情况。

2、特性

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

优点:

  • 文件不分块存储,文件和系统中的文件一一对应
  • 对文件内容做 hash 处理,避免出现重复文件,节约磁盘空间
  • 下载文件支持 HTTP 协议,可基于内置 Web Server 或外部 Web Server
  • 支持在线扩容、动态添加卷
  • 支持文件冗余备份和负载均衡
  • 存储服务器上可以保存文件属性(meta-data)
  • V2.0 网络通信采用 libevent,支持大并发访问,整体性能更好

缺点:

  • 直接按文件存储,可直接查看文件内容,缺乏文件安全性
  • 数据同步无校验,存在静默 IO 问题,降低系统可用性
  • 单线程数据同步,仅适合存储小文件(4kb - 500 mb之间)
  • 备份数根据存储分卷(分组)决定,缺乏文件备份数设置灵活性
  • 单个挂载点异常会导致整个存储节点下线
  • 缺乏多机房容灾支持
  • 静态的负载均衡机制

3、角色

  • Tracker Server:跟踪服务器,主要做调度工作,起到均衡的作用,负责管理所有的 storage server 和 group,每个 storage 在启动后会连接 Tracker,告知自己所有的 group 等信息,并保持周期性心跳
  • Storage Server:存储服务器,主要提供容量和备份服务,以 group 为单位,每个 group 内可以有多台 storage server,数据互为备份
  • Client:客户端,上传下载数据的服务器,也就是我们自己的项目所部署在的服务器

4、文件同步

写文件时,客户端将文件写至 group 内一个 storage server 即认为写文件成功,storage server 写完文件后,会由后台线程将文件同步至同 group 内其它的 storage server

每个 storage 写文件后,同时会写一份 binlog,binlog 里不包含文件数据,只包含文件名等元信息,这份 binlog 用于后台同步,storage 会记录向 group 内其它 storage 同步的进度,以便重启后能接上次的进度继续同步,进度以时间戳的方式进行记录,所以最好能保证集群内所有 server 的时钟保持同步

storage 的同步进度会作为元数据的一部分汇报到 tracker 上,tracker 在选择读 storage 的时候会以同步进度作为参考

5、client

1
2
3
4
5
6
7
8
9
10
vim /etc/fdfs/client.conf

base_path=/data/fastdfs
tracker_server=fastdfs.com:22122 # tracker 服务器ip 和 端口

# 上传文件
fdfs_upload_file /etc/fdfs/client.conf /usr/local/soft/fox.jpg

# 删除文件
fdfs_delete_file /etc/fdfs/client.conf group/M00/00/00/fox.jpg

6、下载过程

跟上传一样,在下载时客户端可以选择任务 Tracker server

客户端带文件名信息请求 Tracker,Tracker 从文件名中解析出文件的 group、大小、创建时间等信息,然后选择一个 storage 用来服务处理请求,返回对应文件

FastDFS 单机环境搭建

7、编译环境

1
yum install git gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl-devel wget vim -y

8、磁盘目录

说明 位置
所有安装包 /usr/local/soft
数据存储位置 /data/fastdfs/

9、安装 libfastcommon

1
2
3
4
5
6
git clone https://github.com/happyfish100/libfastcommon.git --depth 1


cd libfastcommon/
# 编译安装
./make.sh && ./make.sh install

10、安装 FastDFS

1
2
3
4
5
6
7
8
git clone https://github.com/happyfish100/fastdfs.git --depth 1
cd fastdfs
# 编译安装
./make.sh && ./make.sh install

# 供 nginx 访问使用
cp /usr/local/soft/fastdfs/conf/http.conf /etc/fdfs/
cp /usr/local/soft/fastdfs/conf/mime.types /etc/fdfs/

11、安装 fastdfs-nginx-module

1
2
git clone https://github.com/happyfish100/fastdfs-nginx-module.git --depth 1
cp fastdfs-nginx-module-master/src/mod_fastdfs.conf /etc/fdfs

12、安装 nginx

1
2
3
4
5
wget http://nginx.org/download/nginx-1.20.2.tar.gz
tar -zxvf nginx-1.20.2.tar.gz
# 添加 fastdfs-nginx-module 模块
./configure --add-module=/usr/local/soft/fastdfs-nginx-module/src/
make && make install

13、单机部署

服务器ip:192.168.174.102

1
2
3
4
5
# vim /etc/hosts 添加一行
192.168.174.102 fastdfs.com

# 本地 windows C:\Windows\System32\drivers\etc 修改hosts文件
192.168.174.102 fastdfs.com

14、tracker 配置

1
2
3
4
5
6
mkdir -p /data/fastdfs

vim /etc/fdfs/tracker.conf
# 需要修改的内容如下:
port=22122 # tracker 服务器端口(默认 22122,一般不修改)
base_path=/data/fastdfs # 存储日志和数据的根目录

15、storage 配置

1
2
3
4
5
6
7
vim /etc/fdfs/storage.conf
# 需要修改的内容如下
posrt=23000
base_path=/data/fastdfs # 数据和日志文件存放目录
store_path0=/data/fastdfs # 第一个存储目录
tracker_server=fastdfs.com:22122
http.server_port=8888

16、启动服务

1
2
3
4
5
6
7
8
9
# 永久关闭防火墙
systemctl disable firewalld.service

# 启动 tracker
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf
# 启动 storage
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf
# 重启 storage
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart

17、client 测试

1
2
3
4
5
6
7
8
9
10
11
12
vim /etc/fdfs/client.conf

# 需要修改的内容如下
base_path=/data/fastdfs
tracker_server=fastdfs.com:22122 # tracker 服务器 ip 和端口

# 保存后测试,返回 ID 表示成功,如:group1/M00/00/00/wKiuZmHnvMaAWdC1AAQ6yuhOHcs218.jpg
# 上传文件
fdfs_upload_file /etc/fdfs/client.conf /usr/local/soft/fox.jpg

# 删除文件
fdfs_delete_file /etc/fdfs/client.conf group/M00/00/00/fox.jpg

18、配置 nginx 访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
vim /etc/fdfs/mod_fastdfs.conf

# 需要修改的内容如下
tracker_server=fasrdfs.com:22122 # tracker 服务器 ip 和端口
url_have_group_name=true
store_path0=/data/fastdfs

# 配置 nginx.config
vim /usr/local/nginx/conf/nginx.conf
# 添加如下配置
server{
listen 8888; # 该端口为 storage.conf 中的 http.server_port 相同
server_name localhost;
location ~/group[0-9]/{
ngx_fastdfs_module;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html{
root html;
}
}

# nginx
/usr/local/nginx/sbin/nginx # 启动nginx
/usr/local/nginx/sbin/nginx -s reload # 重启 nginx
/usr/local/nginx/sbin/nginx -s stop # 停止 n

19、访问效果

image-20220120093201193

与 springboot 结合

20、引入依赖

1
2
3
4
5
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.27.2</version>
</dependency>

21、编写配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
server.port=8888

# 分布式文件系统 FDFS 配置
# 读取时间
fdfs.so-timeout=1500
# 连接超时时间
fdfs.connect-timeout=600
# 缩略图生成参数
fdfs.thumb-image.width=150
fdfs.thumb-image.height=150
# tracker 服务配置地址列表
fdfs.tracker-list=192.168.174.102:22122
# 从池中借出的对象的最大数目(配置为 -1 表示不限制)
fdfs.pool.max-total=-1
# 获取连接时的最大等待毫秒数(默认配置为 5s)
fdfs.pool.max-wait-millis=5000
# 每个key的最大连接数
fdfs.pool.max-total-per-key=50
# 每个key对应的连接池最大空闲连接数
fdfs.pool.max-idle-per-key=10
# 每个key对应的连接池最小空闲连接数
fdfs.pool.min-idle-per-key=5

upload.base-url=http://fastdfs.com:8888/

spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=150MB

22、controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private final FastFileStorageClient fastFileStorageClient;

@Value("${upload.base-url}")
private String basePath;

@SneakyThrows
@PostMapping("uploadFile")
public String uploadFile(MultipartFile file) {
String suffix = FileUtil.getSuffix(file.getOriginalFilename());
// 上传文件并生成缩略图
StorePath storePath = fastFileStorageClient.uploadImageAndCrtThumbImage(file.getInputStream(), file.getSize(), suffix, null);
String path = basePath + storePath.getFullPath();
log.info(path);
return path;
}
  • Copyrights © 2022-2023 hqz

请我喝杯咖啡吧~

支付宝
微信