FastDFS分布式存储
什么是FastDFS
FastDFS是一个开源的轻量级分布式文件系统。它解决了大量数据存储和负载均衡等问题。适合存储一些视频、音频、图片、文档,允许单个文件的大小为4kb~500MB,在UC基于FastDFS开发向用户提供了:网盘、社区、广告和应用下载等业务的存储服务。
支持Linux和FreeBSD等UNIX系统类google FS,不是通用的文件系统,只能通过专有API访问,目前提供了C、Java和PHP API互为互联网应用量身定做,解决大容量文件存储问题,追求高性能和高扩展性,FastDFS可以看做是基于文件的key value pair存储系统,称作分布式文件存储服务更为合适。
FastDFS相关概念
FastDFS服务端有三个角色:跟踪服务器(tracker server)、存储节点(storage server)、客户端(client)
1、client:客服端,负责进行文件存储和上传等操作
2、tracker server:跟踪服务器,管理后端存储节点,对来自客户端的请求进行识别并制定对应的后端节点给予响应。起负载均衡的作用。在内存中记录集群中所有存储组和存储服务器的状态信息,是客户端和数据服务器交互的枢纽。占用内存量很少。
Tracker是FastDFS的协调者,负责管理所有的storage server和group,每个storage在启动后会连接Tracker,告知自己所属的group等信息,并保持周期性的心跳,tracker根据storage的心跳信息,建立group和storage server的映射表
3、storage server:存储节点,负责响应文件存储、下载、查看,以组或者卷为单位,一个group包含多台storage机器,数据互为备份,相同组的storage数据是完全相同的,所以相同组之间的storage配置尽量相同,以免造成存储空间的浪费
group内每个storage的存储依赖于本地文件系统,storage可配置多个数据存储目录,比如有10块磁盘,分别挂载在
/data/disk1-/data/disk10
,则可将这10个目录都配置为storage的数据存储目录。storage接受到写文件请求时,会根据配置好的规则(后面会介绍),选择其中一个存储目录来存储文件。为了避免单个目录下的文件数太多,在storage第一次启动时,会在每个数据存储目录里创建2级子目录,每级256个,总共65536个文件,新写的文件会以hash的方式被路由到其中某个子目录下,然后将文件数据直接作为一个本地文件存储到该目录中。
文件上传流程
当客户端发出上传数据的请求时,tracker会返回storage服务器的ip和端口,客户端根据返回的ip和端口请求对应的storage上传文件,storage接收到请求后,将文件写入磁盘,并生成file_id,返回给客户端,客户端保存相关信息(file_id包括上传文件在storage所在的路径以及文件名)
FastDFS选择机制
1、选择tracker server
当集群中不止一个tracker server时,由于tracker之间是完全对等的关系,客户端在upload文件时可以任意选择一个tracker。 选择存储的group 当tracker接收到upload file的请求时,会为该文件分配一个可以存储该文件的group,支持如下选择group的规则:
- Round robin,所有的group间轮询
- Specified group,指定某一个确定的group
- Load balance,剩余存储空间多的group优先
2、选择storage server
当选定group后,tracker会在group内选择一个storage server给客户端,支持如下选择storage的规则:
- Round robin,在group内的所有storage间轮询
- First server ordered by ip,按ip排序
- First server ordered by priority,按优先级排序(优先级在storage上配置)
3、选择storage path
当分配好storage server后,客户端将向storage发送写文件请求,storage将会为文件分配一个数据存储目录,支持如下规则:
- Round robin,多个存储目录间轮询
- 剩余存储空间最多的优先
4、生成file_id
选定存储目录之后,storage会为文件生一个file_id,由storage server ip、文件创建时间、文件大小、文件crc32和一个随机数拼接而成,然后将这个二进制串进行base64编码,转换为可打印的字符串。 选择两级目录 当选定存储目录之后,storage会为文件分配一个file_id,每个存储目录下有两级256*256的子目录,storage会按文件file_id进行两次hash(猜测),路由到其中一个子目录,然后将文件以file_id为文件名存储到该子目录下。
5、生成文件名
当文件存储到某个子目录后,即认为该文件存储成功,接下来会为该文件生成一个文件名,文件名由group、存储目录、两级子目录、file_id、文件后缀名(由客户端指定,主要用于区分文件类型)拼接而成。
文件下载流程
客户端下载是必须使用上传是返回的file_id来进行指定文件的下载,发出请求后,tracker会查询对应group的storage的ip以及端口返回给客户端,然后客户端使用file_id与storage直接请求,然后由storage返回文件给客户端。
由于group内的文件同步时在后台异步进行的,所以有可能出现在读到时候,文件还没有同步到某些storage server上,为了尽量避免访问到这样的storage,tracker按照如下规则选择group内可读的storage:
- 该文件上传到的源头storage - 源头storage只要存活着,肯定包含这个文件,源头的地址被编码在文件名中。
- 文件创建时间戳==storage被同步到的时间戳 且(当前时间-文件创建时间戳) > 文件同步最大时间(如5分钟) - 文件创建后,认为经过最大同步时间后,肯定已经同步到其他storage了。
- 文件创建时间戳 < storage被同步到的时间戳。 - 同步时间戳之前的文件确定已经同步了
- (当前时间-文件创建时间戳) > 同步延迟阀值(如一天)。 - 经过同步延迟阈值时间,认为文件肯定已经同步了。
FastDFS整体架构图
1、每个小组的节点之间的数据完全相同,互为备份
2、各个小组的数据没有重复,加起来是整体架构存储的所有数据
部署FastDFS环境
实验环境
主机IP | 服务 | 备注 |
---|---|---|
192.168.1.1 | Client/Nginx | 可联网 |
192.168.1.4 | tracker server1 | 可联网 |
192.168.1.5 | tracker server2 | 可联网 |
192.168.1.6 | storage group1-1/Nginx | 可联网 |
192.168.1.7 | storage group1-2/Nginx | 可联网 |
192.168.1.8 | storage group2-1/Nginx | 可联网 |
192.168.1.9 | storage group2-2/Nginx | 可联网 |
实验步骤
安装FastDFS
每台主机进行网络对时,在Xshell连接下,可以同步操作,如果主机间时间不同步,后续操作,可能会出现一些错误
以下操作是在所有主机中进行操作的
ntpdate ntp.ntsc.ac.cn
创建FastDFS的数据和日志所在目录,yuqing是阿里开发本服务的大佬,所以这样命名,在配置文件中默认指了这个路径,所以需要创建
mkdir -p /home/yuqing/fastdfs
解决依赖关系
yum -y install libtool autoconf automake pcre-devel zlib-devel openssl-devel
解压FastDFS包
tar -zxf fastdfs.tar.gz -C /usr/local/src
cd /usr/local/src
ls
# libfastcommon是fastdfs的lib库,fastdfs是主程序
# fastdfs-nginx-module存放了与nginx相连接的模块,后面会用到
fastdfs fastdfs-nginx-module libfastcommon
安装FastDFS的lib库
cd /usr/local/src/libfastcommon/
./make.sh && ./make.sh install
安装FastDFS主程序
cd ../fastdfs
./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 /usr/local/src/fastdfs/conf/http.conf /etc/fdfs
cp /usr/local/src/fastdfs/conf/mime.types /etc/fdfs
安装nginx
在storage的四台服务器上拖入nginx-1.17.8.tar.gz
包,安装nginx
在FastDFS中有一个ngx_http_fastdfs_module.c
模块,来连接nginx与FastDFS,在安装时会加入模块
192.168.1.6、192.168.1.7、192.168.1.8、192.168.1.9执行以下操作
tar zxf nginx-1.17.8.tar.gz -C /usr/src
cd /usr/src/nginx-1.17.8/
./configure --prefix=/usr/local/nginx \
--user=nginx --group=nginx \
--with-http_stub_status_module \
--add-module=/usr/local/src/fastdfs-nginx-module/src/
make && make install
useradd -M -s /sbin/nologin nginx
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin
cp /usr/local/src/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs/
client也需要安装nginx,只需要简单安装即可
192.168.1.1执行以下操作
tar zxf nginx-1.17.8.tar.gz -C /usr/src
cd /usr/src/nginx-1.17.8/
./configure --prefix=/usr/local/nginx --user=nginx --group=nginx
make && make install
useradd -M -s /sbin/nologin nginx
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin
在client添加反向代理
vim /usr/local/nginx/conf/nginx.conf
# server{}上面http{}下面添加不同组的storage的ip
upstream storage_group1 {
server 192.168.1.6:8888 max_fails=2 fail_timeout=30s;
server 192.168.1.7:8888 max_fails=2 fail_timeout=30s;
}
upstream storage_group2 {
server 192.168.1.8:8888 max_fails=2 fail_timeout=30s;
server 192.168.1.9:8888 max_fails=2 fail_timeout=30s;
}
# 在server里面添加
location ~/group1/ {
proxy_pass http://storage_group1;
}
location ~/group2/ {
proxy_pass http://storage_group2;
}
调整配置文件
修改client主机的clien.conf
配置文件
vim /etc/fdfs/client.conf
# 添加两台tracker的ip地址
tracker_server=192.168.1.4:22122
tracker_server=192.168.1.5:22122
修改tracker(192.168.1.4)主机的tracker.conf
配置文件
vim /etc/fdfs/tracker.conf
# 修改为本机ip
bind_addr=192.168.1.4
# 可以设置允许那些主机使用,没有做任何更改
allow_hosts=*
修改tracker(192.168.1.5)主机的tracker.conf
配置文件
vim /etc/fdfs/tracker.conf
# 修改为本机ip
bind_addr=192.168.1.5
修改storage1-1(192.168.1.6)主机的storage.conf
配置文件
vim /etc/fdfs/storage.conf
# 组号要与1-2的相同
group_name=group1
# 修改为本机ip
bind_addr=192.168.1.6
# 修改为两台tacker的ip
tracker_server=192.168.1.4:22122
tracker_server=192.168.1.5:22122
# 注意fastdfs规定nginx的端口号为8888,一会需要修改nginx端口号
http.server_port=8888
修改storage1-2(192.168.1.7)主机的storage.conf
配置文件
vim /etc/fdfs/storage.conf
# 组号要与1-1的相同
group_name=group1
# 修改为本机ip
bind_addr=192.168.1.7
# 修改为两台tacker的ip
tracker_server=192.168.1.4:22122
tracker_server=192.168.1.5:22122
修改storage2-1(192.168.1.8)主机的storage.conf
配置文件
vim /etc/fdfs/storage.conf
# 组号要与2-2的相同,不能与1-1和1-2的group号相同
group_name=group2
# 修改为本机ip
bind_addr=192.168.1.8
# 修改为两台tacker的ip
tracker_server=192.168.1.4:22122
tracker_server=192.168.1.5:22122
修改storage2-2(192.168.1.9)主机的storage.conf
配置文件
vim /etc/fdfs/storage.conf
# 组号要与2-1的相同,不能与1-1和1-2的group号相同
group_name=group2
# 修改为本机ip
bind_addr=192.168.1.9
# 修改为两台tacker的ip
tracker_server=192.168.1.4:22122
tracker_server=192.168.1.5:22122
修改storage四台主机的mod_fastdfs.conf
配置文件
四台只有group_name
的设置有一些区别,在哪个组改为哪个即可,可以使用scp直接传文件,修改一处即可
vim /etc/fdfs/mod_fastdfs.conf
# 修改
base_path=/home/yuqing/fastdfs
# 修改为两台tacker的ip
tracker_server=192.168.1.4:22122
tracker_server=192.168.1.5:22122
# 哪台主机所在哪个组就改为哪个组号
group_name=group1
# 存储数据的id编号,加入group的组号
url_have_group_name = true
# 更改为组的个数,一共有几个就写几个
group_count = 2
# 取消注释
# 这部分是storage会使用到的模块,所以需要有两个group的信息
[group1]
group_name=group1
storage_server_port=23000
store_path_count=1 # 存储路径个数,存储路径只有一个,改为1即可
store_path0=/home/yuqing/fastdfs
[group2]
group_name=group2
storage_server_port=23000
store_path_count=1
store_path0=/home/yuqing/fastdfs
修改storage四台主机的nginx文件,四台主机完全一样,所以修改一台scp即可
vim /usr/local/nginx/conf/nginx.conf
# 在http模块中添加一个新的server模块
server {
listen 8888;
server_name localhost;
location ~/group[0-9]/M00/ { # 通过匹配group的标识
ngx_fastdfs_module; # 匹配这个fastdfs模块
}
}
scp /usr/local/nginx/conf/nginx.conf 192.168.1.7:/usr/local/nginx/conf/
scp /usr/local/nginx/conf/nginx.conf 192.168.1.8:/usr/local/nginx/conf/
scp /usr/local/nginx/conf/nginx.conf 192.168.1.9:/usr/local/nginx/conf/
启动服务
四台storage启动nginx
nginx -t
nginx
四台storage启动storage
/etc/init.d/fdfs_storaged start
Reloading systemd: [ 确定 ]
Starting fdfs_storaged (via systemctl): [ 确定 ]
启动两台tracker
/etc/init.d/fdfs_trackerd start
Reloading systemd: [ 确定 ]
Starting fdfs_trackerd (via systemctl): [ 确定 ]
client只需要启动nginx即可
nginx -t
nginx
放行防火墙端口或者关闭防火墙
firewall-cmd --add-port=80/tcp
firewall-cmd --add-port=8888/tcp
firewall-cmd --add-port=23000/tcp
firewall-cmd --add-port=22122/tcp
验证
fastdfs常用操作指令
每个操作指定client配置文件是因为需要去连接到tracker去连接存储节点
上传,随便找一张图片做示例,命名为1.jpg
fdfs_upload_file /etc/fdfs/client.conf /root/1.jpg
# 指定client.conf是因为里面写了关于tracker的位置
# /root/1.jpg是指定要上传的文件
# 报错为以下,关闭防火墙即可
[2020-03-04 12:00:49] ERROR - file: connection_pool.c, line: 130, connect to 192.168.1.5:22122 fail, errno: 113, error info: No route to host
# 正确执行完成后,返回存储路径及file_ID
group2/M00/00/00/wKgBCF5fKHCAHzKeAACGCKJq85Q948.jpg
# 它会存储在/home/yuqing/fastdfs/data/00/00/file_ID
以上表示上传成功,可以看到返回信息中,是存储在了group2中,所以在group2的两台主机都能找到该数据,数据存放在/home/yuqing/fdfs/
目录中,根据返回信息的路径可以查看该数据
cd /home/yuqing/fastdfs/data/00/00/
ls
wKgBCF5fKHCAHzKeAACGCKJq85Q948.jpg
查看,访问client的ip加上传成功后的file_ID路径即可
http://192.168.1.1/group2/M00/00/00/wKgBCF5fKHCAHzKeAACGCKJq85Q948.jpg
下载
fdfs_download_file /etc/fdfs/client.conf \
group2/M00/00/00/wKgBCF5fKHCAHzKeAACGCKJq85Q948.jpg \
/root/2.jpg
删除
fdfs_delete_file /etc/fdfs/client.conf \
group2/M00/00/00/wKgBCF5fKHCAHzKeAACGCKJq85Q948.jpg