FastDFS 是一个由 C 语言实现的开源轻量级分布式文件系统,作者余庆(happyfish100),支持 Linux、FreeBSD、AID 等 Unix 系统,解决了大数据存储和读写负载均衡等问题,适合存储 4KB~500MB 之间的小文件,如图片网站、短视频网站、文档、app 下载站等,UC、京东、支付宝、迅雷、酷狗等都有使用。
该软件作者是阿里巴巴大牛、chinaUnix版主余庆个人独立开发的。
技术论坛: http://bbs.chinaunix.net/forum-240-1.html
FAQ:http://bbs.chinaunix.net/thread-1920470-1-1.html
资源地址: https://sourceforge.net/projects/fastdfs/
源码资源: https://github.com/happyfish100
FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。
FastDFS为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。
FastDFS服务端有两个角色:跟踪器(tracker)和存储节点(storage)。
跟踪器主要做调度工作,在访问上起负载均衡的作用。
存储节点存储文件,完成文件管理的所有功能:就是这样的存储、同步和提供存取接口,FastDFS同时对文件的metadata进行管理。
所谓文件的meta data就是文件的相关属性,以键值对(key value)方式表示,如:width=1024,其中的key为width,value为1024。文件metadata是文件属性列表,可以包含多个键值对。
跟踪器和存储节点都可以由一台或多台服务器构成。跟踪器和存储节点中的服务器均可以随时增加或下线而不会影响线上服务。其中跟踪器中的所有服务器都是对等的,可以根据服务器的压力情况随时增加或减少。
为了支持大容量,存储节点(服务器)采用了**分卷(或分组)**的组织方式。存储系统由一个或多个卷组成,卷与卷之间的文件是相互独立的,所有卷的文件容量累加就是整个存储系统中的文件容量。一个卷可以由一台或多台存储服务器组成,一个卷下的存储服务器中的文件都是相同的,卷中的多台存储服务器起到了冗余备份和负载均衡的作用。
在卷中增加服务器时,同步已有的文件由系统自动完成,同步完成后,系统自动将新增服务器切换到线上提供服务。
当存储空间不足或即将耗尽时,可以动态添加卷。只需要增加一台或多台服务器,并将它们配置为一个新的卷,这样就扩大了存储系统的容量。
FastDFS中的文件标识分为两个部分:卷名和文件名,二者缺一不可。
有人在生产环境中使用FastDFS吗?
答案是肯定的。据我所知,截止2012年底至少有25家公司在使用FastDFS,其中有好几家是做网盘的公司。
其中存储量最大的一家,集群中存储group数有400个,存储服务器超过800台,存储容量达到6PB,文件数超过1亿,Group持续增长中。。。
以下是使用FastDFS的用户列表:
某大型网盘(因对方要求对公司名保密,就不提供名字了。有400个group,存储容量达到了6PB,文件数超过1亿)
UC (http://www.uc.cn/,存储容量超过10TB)
支付宝(http://www.alipay.com/)
京东商城(http://www.360buy.com/)
淘淘搜(http://www.taotaosou.com/)
飞信(http://feixin.1008**/)
赶集网(http://www.ganji.com/)
淘米网(http://www.61.com/)
迅雷(http://www.xunlei.com/)
蚂蜂窝(http://www.mafengwo.cn/)
丫丫网(http://www.iyaya.com/)
虹网(http://3g.ahong.com)
5173(http://www.5173.com/)
华夏原创网(http://www.yuanchuang.com/)
华师京城教育云平台(http://www.hsjdy.com.cn/)
视友网(http://www.cuctv.com/)
搜道网(http://www.sodao.com/)
58同城(http://www.58.com/)
商务联盟网(http://www.biz72.com/)
中青网(http://www.youth.cn/)
缤丽网 (http://www.binliy.com/)
飞视云视频(http://www.freeovp.com/)
梦芭莎(http://www.moonbasa.com/)
活动帮(www.eventsboom.com)
51CTO(http://www.51cto.com/)
搜房网(http://www.soufun.com/)
tracker Server:
Storage Server:
group:组,也称为卷。同组内服务器上的文件是完全相同的
文件标识:包括两部分:组名和文件名(包含路径)
meta data:文件相关属性,键值对(Key Value Pair)方式,如:width=1024,heigth=768
内部机制 流程如下:
1、选择tracker server
当集群中不止一个tracker server时,由于tracker之间是完全对等的关系,客户端在upload文件时可以任意选择一个trakcer。
选择存储的group
当tracker接收到upload file的请求时,会为该文件分配一个可以存储该文件的group,支持如下选择group的规则:
2、选择storage server
当选定group后,tracker会在group内选择一个storage server给客户端,支持如下选择storage的规则:
3、选择storage path
当分配好storage server后,客户端将向storage发送写文件请求,storage将会为文件分配一个数据存储目录,支持如下规则:
4、生成Fileid
选定存储目录之后,storage会为文件生一个Fileid,由storage server ip、文件创建时间、文件大小、文件crc32和一个随机数拼接而成,然后将这个二进制串进行base64编码,转换为可打印的字符串。
选择两级目录
当选定存储目录之后,storage会为文件分配一个fileid,每个存储目录下有两级256*256的子目录,storage会按文件fileid进行两次hash(猜测),路由到其中一个子目录,然后将文件以fileid为文件名存储到该子目录下。
5、生成文件名
当文件存储到某个子目录后,即认为该文件存储成功,接下来会为该文件生成一个文件名,文件名由group、存储目录、两级子目录、fileid、文件后缀名(由客户端指定,主要用于区分文件类型)拼接而成。
每个storage写文件后,同时会写一份binlog,binlog里不包含文件数据,只包含文件名等元信息,这份binlog用于后台同步,storage会记录向group内其他storage同步的进度,以便重启后能接上次的进度继续同步;进度以时间戳的方式进行记录,所以最好能保证集群内所有server的时钟保持同步。
指标 | FastDFS | NFS | 集中存储设备 如NetApp、NAS |
---|---|---|---|
线性扩容性 | 高 | 差 | 差 |
文件高并发访问性能 | 高 | 差 | 一般 |
文件访问方式 | 专有API | POSIX | 支持POSIX |
硬件成本 | 较低 | 中等 | 高 |
相同内容文件只保存一份 | 支持 | 不支持 | 不支持 |
指标 | FastDFS | mogileFS |
---|---|---|
系统简洁性 | 简洁 只有两个角色:tracker和storage | 一般 有三个角色:tracker、storage和存储文件信息的mysql db |
系统性能 | 很高(没有使用数据库,文件同步直接点对点,不经过tracker中转) | 高(使用mysql来存储文件索引等信息,文件同步通过tracker调度和中转) |
系统稳定性 | 高(C语言开发,可以支持高并发和高负载) | 一般(Perl语言开发,高并发和高负载支持一般) |
软RAID方式 | 分组(组内冗余),灵活性较大 | 动态冗余,灵活性一般 |
通信协议 | 专有协议 下载文件支持HTTP | HTTP |
技术文档 | 较详细 | 较少 |
文件附加属性(meta data) | 支持 | 不支持 |
相同内容文件只保存一份 | 支持 | 不支持 |
下载文件时支持文件偏移量 | 支持 | 不支持 |
准备linux服务器或虚拟机
Tracker 和 Storage 安装在一台机器上
FastDFS是C语言开发,安装必须使用make、cmake和gcc编译器。建议在linux上运行,本教程使用Centos7.0作为安装环境。
安装gcc 依赖环境 yum install gcc-c++ -y
如安装redis的时候,可能需要 yum install gcc-c++ -y automake autoconf 这个两个依赖。
如果没有外网:则需要安装本地yum源
yum install -y make cmake gcc gcc-c++
libfastcommon是从FastDFS 和FastDHT 中提取出来的公共C函数库
tar -zxvf libfastcommonV1.0.7.tar.gz
libfastmon没有提供make命令安装文件。使用的是shell脚本执行编译和安装。
编译
./make.sh
安装
如果出现编译perl 不识别 运行下面这段命令 – os7
yum -y install zlib zlib-devel pcre pcre-devel gcc gcc-c++ openssl openssl-devel libevent libevent-devel perl unzip net-tools wget
有固定的默认安装位置。在/usr/lib64和/usr/include/fastcommon两个目录中。
注意:libfastcommon安装好后会自动将库文件拷贝至/usr/lib64下,由于FastDFS程序引用/usr/lib目录,所以需要将/usr/lib64下的库文件拷贝至/usr/lib下。
因为 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
快速说明: tracker编译安装
1、上传资料FastDFS_v5.05.tar.gz到 /usr/local 目录下
2、解压编译安装
tar -zxvf FastDFS_v5.05.tar.gz
cd FastDFS
./make.sh
./make.sh install
3、安装成功之后,将安装目录下的conf下的文件拷贝到/etc/fdfs/下。
cd conf
cp * /etc/fdfs/
4、修改配置文件
vim /etc/fdfs/tracker.conf
tar -zxf FastDFS_v5.05.tar.gz -C /usr/local/fastdfs
./make.sh
./make.sh install
安装后,FastDFS主程序所在位置:
/usr/bin - 可执行文件所在位置。
/etc/fdfs - 配置文件所在位置。
/usr/lib64 - 主程序代码所在位置
/usr/include/fastdfs - 包含的一些插件组所在位置
目录 | 说明 |
---|---|
/opt/fastdfs/ | 数据文件及日志 |
/usr/bin/fdfs_trackerd 、 fdfs_storaged | 启动执行程序 |
/usr/local/fdfs/stop.sh 、 restart.sh | 关闭、重启脚本 |
/etc/init.d/fdfs_tracked 、fdfs_storaged | 服务启动脚本 |
/etc/fdfs/ | 配置文件 |
在/etc/init.d/目录中,脚本文件是 fdfs-storaged和fdfs-trackerd
配置文件在/etc/fdfs/
目录中
tracker.conf.sample - 跟踪器服务配置文件模板
storage.conf.sample - 存储服务器配置文件模板
client.conf.sample - FastDFS提供的命令行客户端配置文件模板。可以通过命令行测试FastDFS有效性。
复制一份模板配置文件,在tracker.conf中去配置
cd /etc/fdfs
cp tracker.conf.sample tracker.conf
打开 tracker.conf
修改 base_path 路径,base_path是FastDFSTracker启动后使用的根目录,用来存放Tracker data和logs。
base_path=/home/yuqing/fastdfs -> base_path=/opt/fastdfs(自定义目录)
配置中的路径需要先创建好才能启动服务
mkdir -p /opt/fastdfs
下面以注册服务的方式说明
mkdir /usr/local/fdfs
拷贝安装目录/usr/local/FastDFS下stop.sh 和restart.sh 到/usr/local/fdfs/
cp restart.sh /usr/local/fdfs/
cp stop.sh /usr/local/fdfs/
vim /etc/init.d/fdfs_trackerd
cd /etc/init.d/
chkconfig --add fdfs_trackerd
可以使用 chkconfig --list 查看是否已经添加成功!
下面就可以通过service fdfs_tracker start启动了
如果启动失败,或者报错。请检查上面的操作,重新配置!!!
Storage是配置文件存放的地方
创建fdfs_storage文件夹
mkdir /opt/fastdfs/fdfs_storage
修改配置文件storage.conf
说明:
vim /etc/fdfs/storage.conf
#行号:41,109,118
# 41行修改
base_path=/opt/fastdfs
# 109行修改 文件真实存放的位置
# 需要新建改目录 mkdir fdfs_storage
store_path0=/opt/fastdfs/fdfs_storage
# 118行修改 tracker的服务地址
tracker_server=192.168.100.171:22122
vim /etc/init.d/fdfs_storaged
这个修改和上面的一样,主要是修改五个地方。说明修改原因:主要是把restart.sh和stop.sh这两个文件复制到/usr/local/fdfs/
chkconfig - -add fdfs_storaged
chkconfig --list
启动服务
service fdfs_storaged start
cd /etc/fdfs
cp storage.conf.sample storage.conf
mkdir -p /var/data/fastdfs-storage/base
mkdir -p /var/data/fastdfs-storage/store
要求tracker服务必须已启动
service fdfs_storage start
启动成功后,配置文件中base_path指向的目录中出现FastDFS服务相关数据目录(data目录、logs目录)
配置文件中的store_path0指向的目录中同样出现FastDFS存储相关数据录(data目录)
其中$store_path0/data/目录中默认创建若干子孙目录(两级目录层级总计256256个目录),是用于存储具体文件数据的。
Storage服务器启动比较慢,因为第一次启动的时候,需要创建256256个目录。
FastDFS安装成功可通过/usr/bin/fdfs_test测试上传、下载等操作。
client.conf配置文件中主要描述客户端的行为,需要进行下述修改:
vim /etc/fdfs/client.conf
# 修改base_path
# base_path - 就是客户端命令行执行过程时临时数据存储位置。
base_path=/home/yuqing/fastdfs -> base_path=/opt/fastdfs/client (自定义目录)
# 修改tracker_server
tracker_server=192.168.150.11:22122 -> tracker_server= tracker服务IP:22122
通过/usr/bin/fdfs_test测试上传、下载等操作
/usr/bin/fdfs_test /etc/fdfs/client.conf upload /root/2020.jpg
上传结束后,返回group1/M00/00/00/xxxxxxxxxx.xxx,检查storage服务结点中的 s t o r e p a t h 0 / d a t a / 00 / 00 / 目 录 中 是 否 有 上 传 的 文 件 ( 一 般 情 况 上 传 的 文 件 按 顺 序 保 存 在 store_path0/data/00/00/目录中是否有上传的文件(一般情况上传的文件按顺序保存在 storepath0/data/00/00/目录中是否有上传的文件(一般情况上传的文件按顺序保存在store_path0/data/00/00/目录中,不能完全保证)。
上传文件结果:group1/M00/00/00/wKhkq17oeeSAIPGoAAC6XqVqo6A044_big.jpg
/usr/bin/fdfs_delete_file 删除文件
/usr/bin/fdfs_delete_file /etc/fdfs/client.conf group1/M00/00/00/wKiWDV0xfqWAFe1OAAAib-i5DLU637.log
如果FastDFS中保存的是图片信息。希望在WEB应用中可以直接访问FastDFS中的图片进行显示。如果操作?
安装Nginx是为了WEB应用中可以使用HTTP协议直接访问Storage服务中存储的文件。在storage结点所在服务器安装Nginx组件。
需要安装两部分内容。
Nginx应用,在安装nginx应用的时候,同时要在nginx中增加一个FastDFS的组件。
安装前配置fastdfs-nginx-module
上传fastdfs-nginx-module_v1.16.tar.gz上传到 /usr/local,并解压
tar -zxvf fastdfs-nginx-module_v1.16.tar.gz
编辑配置文件:修改config文件将/usr/local/路径改为/usr/ 3处
vim fastdfs-nginx-module/src/config
上传并解压
tar -zxf fastdfs-nginx-module_v1.16.tar.gz
vim /usr/local/fastdfs/fastdfs-nginx-module/src/config
将fastdfs-nginx-module/src下的mod_fastdfs.conf拷贝至/etc/fdfs/下(配置文件都放在/etc/fdfs/下面)
cp mod_fastdfs.conf /etc/fdfs/
# 并修改mod_fastdfs.conf的内容:
vim /etc/fdfs/mod_fastdfs.conf
修改行号 10,40 ,53,62
修改 url中包含group名称
修改指定文件存储路径
最后,将libfdfsclient.so拷贝至/usr/lib下
cp /usr/lib64/libfdfsclient.so /usr/lib/
安装nginx 需要先配置nginx 的运行环境
Nginx服务器搭建
第一步:安装C语言编译环境
gcc:
yum -y install gcc-c++
第二步:安装第三方的开发包。pcre 、 zlib 、OpenSSL
PCRE
PCRE(Perl Compatible Regular Expressions)是一个Perl库,包括 Perl 兼容的正则表达式库。Nginx的HTTP模块使用PCRE来解析正则表达式,所以需要在Linux上安装PCRE库。
yum install -y pcre pcre-devel
注:pcre-devel是使用PCRE开发的一个二次开发库。Nginx也需要这个库。
zlib
zlib库提供了很多种压缩和解压缩的方式,Nginx使用zlib对HTTP包的内容进行gzip,所以需要在Linux上安装zlib库。
yum install -y zlib zlib-devel
OpenSSL
OpenSSL是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用。
nginx不仅支持http协议,还支持https(即在ssl协议上传输http),所以需要在linux安装openssl库。
yum install -y openssl openssl-devel
Nginx安装
上传文件
nginx-1.12.2.tar.gz
创建nginx/client目录
解压:nginx-1.12.2.tar.gz
cd nginx-1.12.2
mkdir -p /var/temp/nginx/client
cd /usr/local/nginx-1.12.2的原始程序目录 [/usr/local/nginx-1.12.2]
configure: 表示自动配置nginx 的相关目录!
复制运行下面初始化配置
./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--http-scgi-temp-path=/var/temp/nginx/scgi \
--add-module=/usr/local/fastdfs-nginx-module/src
编译
make
安装
make install
编辑nginx.conf 配置代理!
编辑 nginx 的安装路径的nginx.conf
vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name 192.168.67.204;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /group1/M00/ {
ngx_fastdfs_module;
}
#启动nginx
/usr/local/nginx/sbin/nginx
#重启:
/usr/local/nginx/sbin/nginx -s reload
启动成功,访问之前上传返回的url
http://192.168.100.171/group1/M00/00/00/wKhkq17oeeSAIPGoAAC6XqVqo6A044_big.jpg
cp /root/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs/
tracker_server=192.168.2.109:22122
url_have_group_name = true
store_path0=/var/data/fastdfs-storage/store
复制FastDFS安装包中的两个配置文件(http.conf和mime.types)到/etc/fdfs目录中
在上传文件到FastDFS后,FastDFS会返回group1/M00/00/00/xxxxxxxxxx.xxx。其中group1是卷名,在mod_fastdfs.conf配置文件中已配置了url_have_group_name,以保证URL解析正确。
而其中的M00是FastDFS保存数据时使用的虚拟目录,需要将这个虚拟目录定位到真实数据目录上。
ln -s /var/data/fastdfs-storage/store/data/ /var/data/fastdfs-storage/store/data/M00
location ~ /group([0-9])/M00 {
ngx_fastdfs_module;
}
http://192.168.150.11/group1/M00/00/00/wKiWC10xxc6AfHCKAAAib-i5DLU543_big.log
add_header Content-Disposition "attachment;filename=$arg_attname";
https://github.com/tobato/FastDFS_Client
RAID
配置
fdfs:
so-timeout: 1500
connect-timeout: 600
tracker-list:
- 192.168.150.13:22122
// 元数据
Set metaDataSet = new HashSet();
metaDataSet.add(new MetaData("Author", "yimingge"));
metaDataSet.add(new MetaData("CreateDate", "2016-01-05"));
try {
StorePath uploadFile = null;
uploadFile = fc.uploadFile(filename.getInputStream(), filename.getSize(), getFileExtName(filename.getOriginalFilename()), metaDataSet);
account.setPassword(password);
account.setLocation(uploadFile.getPath());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
获取文件后缀
private String getFileExtName(String name) {
// TODO Auto-generated method stub
return (name.substring(name.lastIndexOf(".")+1));
}
或
FilenameUtils.getExtension
返回结果带group
uploadFile.getFullPath() : group1/M00/00/00/wKiWDV0u7ZKALKtNAAADP9sEx2w432.sql
不带group
uploadFile.getPath() : M00/00/00/wKiWDV0u7ZKALKtNAAADP9sEx2w432.sql
配置
thumb-image:
width: 150
height: 150
uploadFile = fc.uploadImageAndCrtThumbImage(filename.getInputStream(), filename.getSize(), FilenameUtils.getExtension(filename.getOriginalFilename()), metaDataSet);
@RequestMapping("/down")
@ResponseBody
public ResponseEntity 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);
}