来源:一叶知秋
作者:知秋
这里简单说下fastdfs
的说明搭建使用,回头专门出附章来讲这块的api
和各种配置,这里就来过简易版的,能进行开发就可。
什么是FastDFS
FastDFS
是一个开源的轻量级分布式文件系统。它解决了大数据量存储和负载均衡等问题。特别适合以中小文件(建议范围:4KB< file_size <500MB)
为载体的在线服务,如相册网站、视频网站等等。
FastDFS
是用c语言编写的一款开源的分布式文件系统。FastDFS
为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用FastDFS
很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。
FastDFS的设计理念
和现有的类Google FS
分布式文件系统相比,FastDFS
的架构和设计理念有其独到之处,主要体现在轻量级
、分组方式
和对等结构
三个方面。
轻量级
FastDFS
只有两个角色:Tracker server
和Storage server
。Tracker server
作为中心结点,其主要作用是负载均衡和调度。
Tracker server
在内存中记录分组
和Storage server
的状态等信息,不记录文件索引信息,占用的内存量很少。另外,客户端(应用)和Storage server
访问Tracker server
时,Tracker server
扫描内存中的分组和Storage server
信息,然后给出应答。由此可以看出Tracker server
非常轻量化,不会成为系统瓶颈。
FastDFS
中的Storage server
在其他文件系统中通常称作Trunk server
或Dataserver
。Storage server
直接利用OS
的文件系统存储文件。FastDFS
不会对文件进行分块存储,客户端上传的文件和Storage server
上的文件一一对应。
众所周知,大多数网站都需要存储用户上传的文件,如图片、视频、电子文档等。出于降低带宽和存储成本的考虑,网站通常都会限制用户上传的文件大小,例如图片文件不能超过5MB、视频文件不能超过100MB等。我认为,对于互联网应用,文件分块存储没有多大的必要。它既没有带来多大的好处,又增加了系统的复杂性。FastDFS
不对文件进行分块存储,与支持文件分块存储的DFS
相比,更加简洁高效,并且完全能满足绝大多数互联网应用的实际需要。
在FastDFS
中,客户端上传文件时,文件ID
不是由客户端指定,而是由Storage server
生成后返回给客户端的。文件ID
中包含了组名
、文件相对路径
和文件名
,Storage server
可以根据文件ID
直接定位到文件。因此FastDFS
集群中根本不需要存储文件索引信息,这是FastDFS
比较轻量级的一个例证。而其他文件系统则需要存储文件索引信息,这样的角色通常称作NameServer
。其中mogileFS
采用MySQL
数据库来存储文件索引以及系统相关的信息,其局限性显而易见,MySQL
将成为整个系统的瓶颈。
FastDFS
轻量级的另外一个体现是代码量较小。最新的V2.0
包括了C
客户端API
、FastDHT
客户端API
和PHP extension
等,代码行数不到5.2
万行。
分组方式
类Google FS
都支持文件冗余备份,例如Google FS
、TFS
的备份数是3。一个文件存储到哪几个存储结点,通常采用动态分配的方式。采用这种方式,一个文件存储到的结点是不确定的。举例说明,文件备份数是3,集群中有A、B、C、D四个存储结点。文件1可能存储在A、B、C三个结点,文件2可能存储在B、C、D三个结点,文件3可能存储在A、B、D三个结点。
FastDFS
采用了分组存储
方式。集群由一个或多个组构成,集群存储总容量为集群中所有组的存储容量之和。一个组由一台或多台存储服务器组成,同组内的多台Storage server
之间是互备关系,同组存储服务器上的文件是完全一致的。文件上传、下载、删除等操作可以在组内任意一台Storage server
上进行。类似木桶短板效应,一个组的存储容量为该组内存储服务器容量最小的那个,由此可见组内存储服务器的软硬件配置最好是一致的。采用分组存储方式的好处是灵活、可控性较强
。比如上传文件时,可以由客户端直接指定上传到的组。一个分组的存储服务器访问压力较大时,可以在该组增加存储服务器来扩充服务能力(纵向扩容)。当系统容量不足时,可以增加组来扩充存储容量(横向扩容)。采用这样的分组存储方式,可以使用FastDFS
对文件进行管理,使用主流的Web server
如Apache、nginx
等进行文件下载。
对等结构
FastDFS
集群中的Tracker server
也可以有多台,Tracker server
和Storage server
均不存在单点问题。Tracker server
之间是对等关系,组内的Storage server
之间也是对等关系。传统的Master-Slave
结构中的Master
是单点,写操作仅针对Master
。如果Master
失效,需要将Slave
提升为Master
,实现逻辑会比较复杂。和Master-Slave
结构相比,对等结构中所有结点的地位是相同的,每个结点都是Master,不存在单点问题
。
FastDFS的架构
FastDFS的系统架构 如图:
从图中可以看出,Tracker server之间相互独立,不存在直接联系。
客户端和Storage server
主动连接Tracker server
。Storage server
主动向Tracker server
报告其状态信息,包括磁盘剩余空间、文件同步状况、文件上传下载次数等统计信息。Storage server
会连接集群中所有的Tracker server
,向他们报告自己的状态。Storage server
启动一个单独的线程来完成对一台Tracker server
的连接和定时报告。需要说明的是,一个组包含的Storage server
不是通过配置文件设定的,而是通过Tracker server
获取到的。
不同组的Storage server
之间不会相互通信,同组内的Storage server
之间会相互连接进行文件同步。Storage server
采用binlog
文件记录文件上传、删除等更新操作。binlog
中只记录文件名,不记录文件内容。
文件同步只在同组内的Storage server
之间进行,采用push
方式,即源头服务器同步给目标服务器。只有源头数据才需要同步,备份数据并不需要再次同步,否则就构成环路了。有个例外,就是新增加一台Storage server
时,由已有的一台Storage server
将已有的所有数据(包括源头数据和备份数据)同步给该新增服务器。
Storage server
中由专门的线程根据binlog
进行文件同步。为了最大程度地避免相互影响以及出于系统简洁性考
虑,Storage server
对组内除自己以外的每台服务器都会启动一个线程来进行文件同步。
文件同步采用增量同步方式,系统记录已同步的位置(binlog
文件偏移量)到标识文件中。标识文件名格式:
{dest storage IP}_{port}.mark
,例如:192.168.1.14_23000.mark。
文件上传和下载的交互过程
文件上传流程
接下来我们一起看一下文件上传和下载的交互过程。文件上传流程的步骤如下
Client
询问Tracker server
上传到的Storage server
;Tracker server
返回一台可用的Storage server
,返回的数据为该Storage server
的IP地址和端口;- Client直接和该
Storage server
建立连接,进行文件上传,Storage server
返回新生成的文件ID
,文件上传结束。
再啰嗦点细节:
选择tracker server
当集群中不止一个tracker server时,由于tracker之间是完全对等的关系,客户端在upload文件时可以任意选择一个trakcer。
选择存储的group
当tracker接收到upload file的请求时,会为该文件分配一个可以存储该文件的group,支持如下选择group的规则: 1. Round robin,所有的group间轮询 2. Specified group,指定某一个确定的group 3. Load balance,剩余存储空间多多group优先
选择storage server
当选定group后,tracker会在group内选择一个storage server给客户端,支持如下选择storage的规则: 1. Round robin,在group内的所有storage间轮询 2. First server ordered by ip,按ip排序 3. First server ordered by priority,按优先级排序(优先级在storage上配置)
选择storage path
当分配好storage server后,客户端将向storage发送写文件请求,storage将会为文件分配一个数据存储目录,支持如下规则: 1. Round robin,多个存储目录间轮询 2. 剩余存储空间最多的优先
生成Fileid
选定存储目录之后,storage会为文件生一个Fileid,由storage server ip、文件创建时间、文件大小、文件crc32和一个随机数拼接而成,然后将这个二进制串进行base64编码,转换为可打印的字符串。
选择两级目录
当选定存储目录之后,storage会为文件分配一个fileid,每个存储目录下有两级256*256的子目录,storage会按文件fileid进行两次hash(猜测),路由到其中一个子目录,然后将文件以fileid为文件名存储到该子目录下。
生成文件名
当文件存储到某个子目录后,即认为该文件存储成功,接下来会为该文件生成一个文件名,文件名由group、存储目录、两级子目录、fileid、文件后缀名(由客户端指定,主要用于区分文件类型)拼接而成。
客户端上传文件后存储服务器将文件ID返回给客户端,此文件ID用于以后访问该文件的索引信息。文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名。
文件同步
写文件时,客户端将文件写至group
内一个storage server
即认为写文件成功,storage server
写完文件后,会由后台线程将文件同步至同group
内其他的storage server
。
每个storage
写文件后,同时会写一份binlog
,binlog
里不包含文件数据,只包含文件名等元信息,这份binlog
用于后台同步,storage
会记录向group
内其他storage
同步的进度,以便重启后能接上次的进度继续同步;进度以时间戳的方式进行记录,所以最好能保证集群内所有server
的时钟保持同步。
storage
的同步进度会作为元数据的一部分汇报到tracker
上,tracker
在选择读storage
的时候会以同步进度作为参考。
比如一个group内有A、B、C三个storage server
,A向C同步到进度为T1 (T1以前写的文件都已经同步到B上了),B向C同步到时间戳为T2(T2 > T1),tracker
接收到这些同步进度信息时,就会进行整理,将最小的那个做为C的同步时间戳,本例中T1即为C的同步时间戳为T1(即所有T1以前写的数据都已经同步到C上了);同理,根据上述规则,tracker会为A、B生成一个同步时间戳。
文件下载流程
- Client询问Tracker server可以下载指定文件的Storage server,参数为文件ID(包含组名和文件名);
- Tracker server返回一台可用的Storage server;
- Client直接和该Storage server建立连接,完成文件下载
文件同步延迟问题的提出
客户端将一个文件上传到一台Storage server后,文件上传工作就结束了。由该Storage server根据binlog中的上传记录将这个文件同步到同组的其他Storage server。这样的文件同步方式是异步方式,异步方式带来了文件同步延迟的问题。新上传文件后,在尚未被同步过去的Storage server上访问该文件,会出现找不到文件的现象。
FastDFS是如何解决文件同步延迟这个问题的呢?
文件的访问分为两种情况:文件更新和文件下载。文件更新包括设置文件附加属性和删除文件。文件的附加属性包括文件大小、图片宽度、图片高度等。FastDFS中,文件更新操作都会优先选择源Storage server,也就是该文件被上传到的那台Storage server
。这样的做法不仅避免了文件同步延迟的问题,而且有效地避免了在多台Storage server上更新同一文件可能引起的时序错乱的问题。
那么文件下载是如何解决文件同步延迟这个问题的呢?
要回答这个问题,需要先了解文件名中包含了什么样的信息。Storage server生成的文件名中,包含了源Storage server的IP地址和文件创建时间等字段。文件创建时间为UNIX时间戳,后面称为文件时间戳。从文件名或文件ID中,可以反解出这两个字段。然后我们再来看一下,Tracker server是如何准确地知道一个文件已被同步到一台Storage server上的。前面已经讲过,文件同步采用主动推送的方式。另外,每台storage server都会定时向tracker server报告它向同组的其他storage server同步到的文件时间戳。当tracker server收到一台storage server的文件同步报告后,它会依次找出该组内各个storage server(后称作为S)被同步到的文件时间戳最小值,作为S的一个属性记录到内存中。
FastDFS对文件同步延迟问题的解决方案
下面我们来看一下FastDFS采取的解决方法。
一个最简单的解决办法,和文件更新一样,优先选择源Storage server下载文件即可。这可以在Tracker server的配置文件中设置,对应的参数名为download_server。
另外一种选择Storage server的方法是轮流选择(round-robin)。当Client询问Tracker server有哪些Storage server可以下载指定文件时,Tracker server返回满足如下四个条件之一的Storage server:
该文件上传到的源Storage server,文件直接上传到该服务器上的;
文件创建时间戳 < Storage server被同步到的文件时间戳,这意味着当前文件已经被同步过来了;
文件创建时间戳=Storage server被同步到的文件时间戳,且(当前时间—文件创建时间戳) > 一个文件同步完成需要的最大时间(如5分钟);
(当前时间—文件创建时间戳) > 文件同步延迟阈值,比如我们把阈值设置为1天,表示文件同步在一天内肯定可以完成。
图片服务器的搭建
因为开发所用,这里就搭建个单机版
安装环境 CentOS6.8 64位
需要gcc的编译环境
需要libevent的包。
yum install -y zlib zlib-devel pcre pcre-devel gcc gcc-c++ openssl openssl-devel libevent libevent-devel perl unzip
安装步骤
Tracker的安装
第一步:把源码包上传到linux系统。
第二步:解压缩libfastcommonV1.0.7.tar.gz包。
第三步:进入/root/libfastcommon-1.0.7文件夹执行./make.sh、./make.sh install
安装libfastcommon
下载最新版本: libfastcommon
wget https://github.com/happyfish100/libfastcommon/archive/master.zip
unzip master.zip
cd libfastcommon-master/
./make.sh
./make.sh install
第四步:把/usr/lib64/libfastcommon.so文件向/usr/lib文件夹下复制一份。(32位系统可这么做,64位不需要)
第五步:把FastDFS_v5.05.tar.gz解压缩。
第六步:进入/root/FastDFS目录执行:./make.sh、./make.sh install
wget http://sourceforge.net/projects/fastdfs/files/FastDFS%20Server%20Source%20Code/FastDFS%20Server%20with%20PHP%20Extension%20Source%20Code%20V5.05/FastDFS_v5.05.tar.gz
tar zxf FastDFS_v5.05.tar.gz && cd FastDFS
./make.sh
./make.sh install
\cp -pa conf/*.conf /etc/fdfs/
cd /etc/fdfs/
rm -rf *.sample
第七步:配置trackerServer。
1、 把/root/FastDFS/conf
目录下的所以的文件复制到/etc/fdfs
目录下。
2、 编辑/etc/fdfs/tracker.conf
第八步:启动tracker服务
/usr/bin/fdfs_trackerd/etc/fdfs/tracker.conf restart
Storage服务的安装
如果storage和tracker不在同一台服务上需要重复执行Tracker的安装的第一步到第六步
配置Storage服务:
需要修改/etc/fdfs/storage.conf
文件
启动服务:
[root@localhost fdfs]#/usr/bin/fdfs_storaged /etc/fdfs/storage.conf
测试上传服务
修改客户端的配置文件/etc/fdfs/client.conf
上传文件:
/usr/bin/fdfs_testclient.conf upload xxx.jpg
访问图片
使用FastDFS的Nginx插件和Nginx配合,实现图片的访问。Nginx需要安装到storage服务所在的服务器
安装步骤:
第一步:把插件包解压缩。fastdfs-nginx-module_v1.16.tar.gz
第二步:编辑/root/fastdfs-nginx-module/src/config文件。删除其中的local字样
wget http://nginx.org/download/nginx-1.8.0.tar.gz
http://sourceforge.net/projects/fastdfs/files/FastDFS%20Nginx%20Module%20Source%20Code/fastdfs-nginx-module_v1.16.tar.gz/download
tar zxf fastdfs-nginx-module_v1.16.tar.gz && tar zxf nginx-1.8.0.tar.gz
#修改模块中对应的路径,要不然模块不能正确安装加载
cd fastdfs-nginx-module/src
vi conf #更改如下, 去掉local,并指定lib64(64系统)
CORE_INCS="$CORE_INCS /usr/include/fastdfs /usr/include/fastcommon/"
CORE_LIBS="$CORE_LIBS -L/usr/lib64 -lfastcommon -lfdfsclient"
第三步:把/root/fastdfs-nginx-module/src/mod_fastdfs.conf
文件复制到/etc/fdfs
目录下。
第四步:把/usr/lib64/libfdfsclient.so
文件复制到/usr/lib
目录下(32位系统,64位系统不需要)
第五步:编译Nginx
对Nginx进行config
./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=/root/fastdfs-nginx-module/src
第六步:配置Nginx
第七步:编辑Nginx
插件的配置文件:
修改/etc/fdfs/mod_fastdfs.conf
文件
第八步:启动Nginx
最後,再多说一点 这是之前自己 笔记的一点心得,贴出来
nginx通过插件fastdfs-nginx-module_v1.16.tar管理访问/group1/M00/过来的路径
这是插件的日志路径
# the base path to store log files
base_path=/tmp
这里接收管理storage存放路径
# store_path#, based 0, if store_path0 not exists, it's value is base_path
# the paths must be exist
# must same as storage.conf 注意看这些注释,然后就知道怎么配了
store_path0=/home/fastdfs/storage
通过下面来和索引器联系起来
# valid only when load_fdfs_parameters_from_tracker is true
tracker_server=192.168.42.129:22122
忘说了:
启动测试前,开放端口号端口给浏览器访问
/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT
/sbin/iptables -I INPUT -p tcp --dport 22 -j ACCEPT
/sbin/iptables -I INPUT -p tcp --dport 22122 -j ACCEPT
#然后保存:
/etc/rc.d/init.d/iptables save
#重启防火墙以便改动生效:(或者直接重启系统)
/etc/init.d/iptables restart
往期回顾:
- 【Java实战项目】Migo商城2.0 参考通用mapper思想对service代码的二次优化封装 四
- 【Java实战项目】Migo商城2.0 Nginx的安装与使用 三
- 【Java实战项目】Migo商城2.0 后台管理页面分析及商品类目展示实现 二
- 【Java实战项目】Migo商城2.0 框架搭建 一
更多内容请关注:极乐科技