分布式文件系统

介绍

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

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

FastDFS服务端有两个角色:跟踪器(tracker)和存储节点(storage)。跟踪器主要做调度工作,在访问上起负载均衡的作用。

存储节点存储文件,完成文件管理的所有功能:就是这样的存储、同步和提供存取接口,FastDFS同时对文件的metadata进行管理。所谓文件的meta data就是文件的相关属性,以键值对(key value)方式表示,如:width=1024,其中的key为width,value为1024。文件metadata是文件属性列表,可以包含多个键值对。

跟踪器和存储节点都可以由一台或多台服务器构成。跟踪器和存储节点中的服务器均可以随时增加或下线而不会影响线上服务。其中跟踪器中的所有服务器都是对等的,可以根据服务器的压力情况随时增加或减少。

为了支持大容量,存储节点(服务器)采用了分卷(或分组)的组织方式。存储系统由一个或多个卷组成,卷与卷之间的文件是相互独立的,所有卷的文件容量累加就是整个存储系统中的文件容量。一个卷可以由一台或多台存储服务器组成,一个卷下的存储服务器中的文件都是相同的,卷中的多台存储服务器起到了冗余备份和负载均衡的作用。

在卷中增加服务器时,同步已有的文件由系统自动完成,同步完成后,系统自动将新增服务器切换到线上提供服务。

当存储空间不足或即将耗尽时,可以动态添加卷。只需要增加一台或多台服务器,并将它们配置为一个新的卷,这样就扩大了存储系统的容量。

FastDFS中的文件标识分为两个部分:卷名和文件名,二者缺一不可。

架构

fastDFS

1
2
3
4
5
tracker Server:
- 主节点,跟踪服务器,主要做调度工作,在访问上起负载均衡的作用。
- 记录storage server的状态,是连接Client和Storage server的枢纽。
- FastDFS集群中的Tracker server可以有多台,Trackerserver之间是相互平等关系同时提供服务
- Trackerserver不存在单点故障。客户端请求Trackerserver采用轮询方式,如果请求的tracker无法提供服务则换另一个tracker。
1
2
3
4
5
6
7
Storage Server:
- 存储服务器,文件和meta data都保存到存储服务器上
- storage集群由一个或多个组构成,集群存储总容量为集群中所有组的存储容量之和。
- 一个组由一台或多台存储服务器组成,组内的Storage server之间是平等关系
- 不同组的Storageserver之间不会相互通信,同组内的Storageserver之间会相互连接进行文件同步,从而保证同组内每个storage上的文件完全一致的。
- 一个组的存储容量为该组内存储服务器容量最小的那个,由此可见组内存储服务器的软硬件配置最好是一致的。
- Storage server会连接集群中所有的Tracker server,定时向他们报告自己的状态,包括磁盘剩余空间、文件同步状况、文件上传下载次数等统计信息。
1
2
3
group:组,也称为卷。同组内服务器上的文件是完全相同的
文件标识:包括两部分:组名和文件名(包含路径)
meta data:文件相关属性,键值对(Key Value Pair)方式,如:width=1024,heigth=768

上传流程

fastDFS

1
2
3
- client询问tracker上传到的storage,不需要附加参数;
- tracker返回一台可用的storage;
- client直接和storage通讯完成文件上传

1、选择tracker server

当集群中不止一个tracker server时,由于tracker之间是完全对等的关系,客户端在upload文件时可以任意选择一个trakcer。
选择存储的group
当tracker接收到upload file的请求时,会为该文件分配一个可以存储该文件的group,支持如下选择group的规则:

1
2
3
- 1、Round robin,所有的group间轮询
- 2、Specified group,指定某一个确定的group
- 3、Load balance,剩余存储空间多多group优先

2、选择storage server

当选定group后,tracker会在group内选择一个storage server给客户端,支持如下选择storage的规则:

1
2
3
- 1、Round robin,在group内的所有storage间轮询
- 2、First server ordered by ip,按ip排序
- 3、First server ordered by priority,按优先级排序(优先级在storage上配置)

3、选择storage path

当分配好storage server后,客户端将向storage发送写文件请求,storage将会为文件分配一个数据存储目录,支持如下规则:

1
2
- 1、Round robin,多个存储目录间轮询
- 2、剩余存储空间最多的优先

4、生成Fileid

选定存储目录之后,storage会为文件生一个Fileid,由storage server ip、文件创建时间、文件大小、文件crc32和一个随机数拼接而成,然后将这个二进制串进行base64编码,转换为可打印的字符串。
选择两级目录
当选定存储目录之后,storage会为文件分配一个fileid,每个存储目录下有两级256*256的子目录,storage会按文件fileid进行两次hash(猜测),路由到其中一个子目录,然后将文件以fileid为文件名存储到该子目录下。

5、生成文件名

当文件存储到某个子目录后,即认为该文件存储成功,接下来会为该文件生成一个文件名,文件名由group、存储目录、两级子目录、fileid、文件后缀名(由客户端指定,主要用于区分文件类型)拼接而成。

下载流程

fastDFS

1
2
3
- client询问tracker下载文件的storage,参数为文件标识(组名和文件名);
- tracker返回一台可用的storage;
- client直接和storage通讯完成文件下载。

fastDFS

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

安装

FastDFS下载地址 Nginx应用下载地址 依赖库下载地址

1
2
#FastDFS是C语言开发的应用。安装必须使用make、cmake和gcc编译器。
yum install -y make cmake gcc gcc-c++

安装依赖库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#解压依赖库
unzip libfastcommon-master.zip -d /usr/local/fastdfs

#编译
./make.sh

#安装 有固定的默认安装位置。在/usr/lib64和/usr/include/fastcommon两个目录中。
./make.sh install

#创建软连接
#因为 FastDFS 主程序设置的 lib 目录是/usr/local/lib,所以需要创建软链接
ln -s /usr/lib64/libfastcommon.so /usr/local/lib/libfastcommon.so

ln -s /usr/lib64/libfastcommon.so /usr/lib/libfastcommon.so

ln -s /usr/lib64/libfdfsclient.so /usr/local/lib/libfdfsclient.so

ln -s /usr/lib64/libfdfsclient.so /usr/lib/libfdfsclient.so

安装FastDFS

1
2
3
4
5
6
#上传并解压缩
tar -zxf FastDFS_v5.08.tar.gz -C /usr/local/fastdfs

#编译安装
./make.sh
./make.sh install
1
2
3
4
5
#安装后,FastDFS主程序所在位置:
/usr/bin - 可执行文件所在位置。
/etc/fdfs - 配置文件所在位置。
/usr/lib64 - 主程序代码所在位置
/usr/include/fastdfs - 包含的一些插件组所在位置

配置

在/etc/init.d/目录中,启动脚本文件是 fdfs-storagedfdfs-trackerd

1
2
3
4
配置文件在/etc/fdfs/目录中
- tracker.conf.sample - 跟踪器服务配置文件模板
- storage.conf.sample - 存储服务器配置文件模板
- client.conf.sample - FastDFS提供的命令行客户端配置文件模板。可以通过命令行测试FastDFS有效性。

Tracker服务

1
2
3
4
5
6
7
8
9
10
11
12
13
cd /etc/fdfs
cp tracker.conf.sample tracker.conf

#打开文件修改base_path路径,用来存放Tracker data 和 logs
vi tracker.conf

`
#base_path=/home/yuqing/fastdfs
base_path=/var/data/fastdfs-tracker(自定义目录)
`

#配置的路径需要启动前先创建好
mkdir -p /var/data/fastdfs-tracker
1
2
3
4
5
6
7
8
9
10
11
#启动Tracker
/etc/init.d/fdfs_trackerd start

#查看服务状态
ps -ef | grep fdfs

#停止服务
/etc/init.d/fdfs_trackerd stop

#重启服务
/etc/init.d/fdfs_trackerd restart

Storage服务

1
2
3
4
5
cd /etc/fdfs
cp storage.conf.sample storage.conf

mkdir -p /var/data/fastdfs-storage/base
mkdir -p /var/data/fastdfs-storage/store
1
2
3
4
5
6
7
8
9
10
#修改storage.conf配置文件

#base_path=/home/yuqing/fastdfs
base_path=/var/data/fastdfs-storage/base(自定义目录)

#store_path0=/home/yuqing/fastdfs
store_path0=/var/data/fastdfs-storage/store(自定义目录)

#tracker_server=192.168.150.11:22122
tracker_server=tracker服务IP:22122
1
2
3
- base_path - 基础路径。用于保存storage server基础数据内容和日志内容的目录。
- store_path0 - 存储路径。是用于保存FastDFS中存储文件的目录,就是要创建256*256个子目录的位置。base_path和store_path0可以使用同一个目录。
- tracker_server - 跟踪服务器位置。就是跟踪服务器的ip和端口。
1
2
3
4
5
6
7
8
9
10
11
#启动服务  要求tracker服务必须已启动
/etc/init.d/fdfs_storaged start

#查看服务状态
/etc/init.d/fdfs_storaged status

#停止服务
/etc/init.d/fdfs_storaged stop

#重启服务
/etc/init.d/fdfs_storaged restart

Client服务

1
2
3
4
cd /etc/fdfs
cp client.conf.sample client.conf

mkdir -p /fastdfs/client
1
2
3
4
5
6
7
vi /etc/fdfs/client.conf

#base_path=/home/yuqing/fastdfs
base_path=/fastdfs/client (自定义目录)

#tracker_server=192.168.150.11:22122
tracker_server=tracker服务IP:22122

上传文件

1
2
3
4
[root@node03 data]# /usr/bin/fdfs_upload_file /etc/fdfs/client.conf /root/install.log

#返回的路径
group1/M00/00/00/wKiWDV0xfqWAFe1OAAAib-i5DLU637.log
1
2
3
4
5
6
7
组名:group1   文件上传后所在的storage组名称,在文件上传成功后有storage服务器返回,需要客户端自行保存。

虚拟磁盘路径:M00 storage配置的虚拟路径,与磁盘选项store_path*对应。如果配置了store_path0则是M00,如果配置了store_path1则是M01,以此类推。

数据两级目录:/00/00 storage服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据文件。

文件名:wKiWDV0xfqWAFe1OAAAib-i5DLU637.log

删除文件

1
/usr/bin/fdfs_delete_file /etc/fdfs/client.conf group1/M00/00/00/wKiWDV0xfqWAFe1OAAAib-i5DLU637.log

Nginx组件

如果FastDFS中保存的是图片信息。希望在WEB应用中可以直接访问FastDFS中的图片进行显示。如果操作?

安装Nginx是为了WEB应用中可以使用HTTP协议直接访问Storage服务中存储的文件。在storage结点所在服务器安装Nginx组件。

需要安装两部分内容。

Nginx应用,在安装nginx应用的时候,同时要在nginx中增加一个FastDFS的组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#上传并解压
tar -zxf fastdfs-nginx-module_v1.16.tar.gz

#修改配置
vi /usr/local/fastdfs/fastdfs-nginx-module/src/config

`
CORE_INCS="$CORE_INCS /usr/include/fastdfs /usr/include/fastcommon/"
`

#编译安装Nginx
./configure --prefix=/usr/local/tengine
--add-module=/root/fastdfs-nginx-module/src/

make && make install
1
2
3
4
5
6
7
8
cp /root/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs/
vi mod_fastdfs.conf

`
tracker_server=192.168.2.109:22122
url_have_group_name = true
store_path0=/var/data/fastdfs-storage/store
`

拷贝http服务需要的配置,复制FastDFS安装包中的两个配置文件(http.conf和mime.types)到/etc/fdfs目录中。

1
2
#创建软连接
ln -s /var/data/fastdfs-storage/store/data/ /var/data/fastdfs-storage/store/data/M00

在上传文件到FastDFS后,FastDFS会返回group1/M00/00/00/xxxxxxxxxx.xxx。其中group1是卷名,在mod_fastdfs.conf配置文件中已配置了url_have_group_name,以保证URL解析正确。

而其中的M00是FastDFS保存数据时使用的虚拟目录,需要将这个虚拟目录定位到真实数据目录上。

1
2
3
4
5
6
7
8
9
10
#修改Nginx配置文件

location ~ /group([0-9])/M00 {
ngx_fastdfs_module;
#下载时根据参数attname的值,自定义文件名称
add_header Content-Disposition "attachment;filename=$arg_attname";
}

#请求
#http://192.168.150.11/group1/M00/00/00/wKiWC10xxc6AfHCKAAAib-i5DLU543_big.log

Java组件

1
2
3
4
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
</dependency>
1
2
3
4
5
6
7
8
9
10
#配置
fdfs:
so-timeout: 1500
connect-timeout: 600
tracker-list:
- 192.168.150.13:22122
#配置开启缩略图
thumb-image:
width: 150
height: 150

上传文件

1
2
3
4
5
6
7
8
9
10
11
// 元数据
Set<MetaData> metaDataSet = new HashSet<MetaData>();
metaDataSet.add(new MetaData("Author", "midkuro"));
metaDataSet.add(new MetaData("CreateDate", "2016-01-05"));

StorePath uploadFile = fc.uploadFile(filename.getInputStream(), filename.getSize(), FilenameUtils.getExtension(filename.getOriginalFilename()), metaDataSet);

//返回的路径不带group
System.out.println(uploadFile.getPath());
//返回的路径带group
System.out.println(uploadFile.getFullPath());
1
2
//上传图片并且自动生成缩略图
uploadFile = fc.uploadImageAndCrtThumbImage(filename.getInputStream(), filename.getSize(), FilenameUtils.getExtension(filename.getOriginalFilename()), metaDataSet);

下载文件

1
2
3
4
5
6
7
8
9
10
11
12
@RequestMapping("/down")
@ResponseBody
public ResponseEntity<byte[]> down(HttpServletResponse resp) {

DownloadByteArray cb = new DownloadByteArray();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", "aaa.xx");
byte[] bs = fc.downloadFile("group1", "M00/00/00/wKiWDV0vAb-AcOaYABf1Yhcsfws9181.xx", cb);

return new ResponseEntity<>(bs,headers,HttpStatus.OK);
}

FastDFS集群

fastDFS

最后更新: 2021年02月03日 14:18

原始链接: https://midkuro.gitee.io/2021/02/03/file-FastDFS/

× 请我吃糖~
打赏二维码