FastDFS是一款类Google FS的开源分布式文件系统,它用纯C语言实现,支持Linux、FreeBSD、AIX等UNIX系统。它只能通过专有API对文件进行存取访问,不支持POSIX接口方式,不能mount使用。准确地讲,Google FS以及FastDFS、 mogileFS、HDFS、TFS等类Google FS都不是系统级的分布式文件系统,而是应用级的分布式文件存储服务。
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或Data server。 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的架构
图1展示的是FastDFS的系统架构。
从图1可以看出,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。
文件上传和下载的交互过程
接下来我们一起看一下文件上传和下载的交互过程。文件上传和下载流程分别如图2、图3所示。文件上传流程的步骤如下:
1. Client询问Tracker server上传到的Storage server;
2. Tracker server返回一台可用的Storage server,返回的数据为该Storage server的IP地址和端口;
3. Client直接和该Storage server建立连接,进行文件上传,Storage server返回新生成的文件ID,文件上传结束。
文件下载流程的步骤如下:
1. Client询问Tracker server可以下载指定文件的Storage server,参数为文件ID(包含组名和文件名);
2. Tracker server返回一台可用的Storage server;
3. 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天,表示文件同步在一天内肯定可以完成。
结束语
看了上面的介绍,你是否认为FastDFS比较简洁高效呢?原雅虎同事――一位比较资深的系统架构师听完FastDFS介绍后,作出这样的评价:“FastDFS是穷人的解决方案”。他的意思是说FastDFS把简洁和高效做到了极致,非常节约资源,中小网站完全用得起,这是对FastDFS 的极大认可和褒奖。
FastDFS从2008年7月发布至今,已推出31个版本,后续完善和优化工作正在持续进行中。目前已有多家公司在生产环境中使用FastDFS,相信通过我们的不懈努力,FastDFS一定会越来越好!
本文转载:http://4285797.blog.51cto.com/4275797/1585930
分布式文件系统 FastDFS_V4.06 安装部署
本文转载:http://4285797.blog.51cto.com/4275797/1585924
1.系统环境说明
部署环境 ubuntu 12.0.4 server 32位or 64位,本文以64部署做说明。
最小化系统安装,除openssh-server服务外不安装任何服务,我们的client,tracker server,storage server 用同一台物理机,iP为192.168.0.22
2.分区设置
根据部署的服务要求选择合理的分区,根据公司现有生产环境的分区划分这里做一下分区。
/boot200M
/ 1G
Swap 2倍内存
/www 剩余空间,数据,部署程序,log,备份主要存放地。
3.初始化部署环境
sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrade
安装编译环境
sudo apt-get install build-essential #配置编译器和库文件
sudo dpkg-reconfigure tzdata
或者sudo tzselect
然后在crontab设置服务器时间同步,比如每天凌晨1点15分同步一次网络时钟
15 1 * * * /usr/sbin/ntpdate 210.72.145.44;/sbin/hwclock -w > /dev/null 2>&1 &
4. 安装libevent
下载并安装
#cd /usr/src
wget https://github.com/downloads/libevent/libevent/libevent-1.4.14b-stable.tar.gz
$sudo su -
#tar zxvf libevent-1.4.14b-stable.tar.gz
# cd libevent-1.4.14b-stable
# ./configure --prefix=/usr
# make && make install
5.安装FastDFS
这里我们选择的FDFS新版本,这里的FASTDFS 本身没有了http server的功能。
5.1
#cd /usr/src
#wget http://fastdfs.googlecode.com/files/FastDFS_v4.06.tar.gz
#tar zxvf FastDFS_v4.06.tar.gz
# cd FastDFS/
由于一些库文件的存放位置,和编译脚本中的不一致,需要根据系统的实际情况进行调整。
#vim make.sh
查找:
if [ -f /usr/lib/libpthread.so ] || [ -f /usr/local/lib/libpthread.so ] || [ -f /lib64/libpthread.so ] || [ -f /usr/lib64/libpthread.so ] || [ -f /usr/lib/libpthread.a ] || [ -f /usr/local/lib/libpthread.a ] || [ -
f /lib64/libpthread.a ] || [ -f /usr/lib64/libpthread.a ] ;
注意替换成:(以你服务器的编辑器格式和实际路径为准)
if [ -f /usr/lib/libpthread.so ] || [ -f /usr/local/lib/libpthread.so ] || [ -f /lib64/libpthread.so ] || [ -f /usr/lib64/libpthread.so ] || [ -f /usr/lib/x86_64-linux-gnu/libpthread.so ] || [ -f /usr/lib/libpthread.a ] || [ -f /usr/local/lib/libpthread.a ] || [ -f /lib64/libpthread.a ] || [ -f /usr/lib64/libpthread.a ] || [ -f /usr/lib/x86_64-linux-gnu/libpthread.a ];
保存退出
#vim /usr/src/FastDFS/client/fdfs_link_library.sh.in (64 bit 需要修改)
查找:
ln -fs $TARGET_LIB/libfastcommon.so.1 /usr/lib64/libfastcommon.so
ln -fs $TARGET_LIB/libfdfsclient.so.1 /usr/lib64/libfdfsclient.so
替换成:
ln -fs $TARGET_LIB/libfastcommon.so.1 /usr/lib/x86_64-linux-gnu/libfastcommon.so
ln -fs $TARGET_LIB/libfdfsclient.so.1 /usr/lib/x86_64-linux-gnu/libfdfsclient.so
保存退出
# sudo ./make.sh
sudo ./make.sh install
#cp init.d/* /etc/init.d/
注:如果报perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LANGUAGE = (unset),
LC_ALL = (unset),
LANG = "en_US.UTF-8"
are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
错,需要设置
vim /root/.bashrc
export LC_ALL=C
保存退出
#source /root/.bashrc
6.配置tracker server
安装完成后,在默认
cd /etc/fdfs下
#vim tracker.conf
port=22122
base_path=/www/book_tracker
保存退出
#mkdir /www/book_tracker
# /etc/init.d/fdfs_trackerd start
检查tracker server
#netstat -antpul |grep 22122 或者lsof -i:22122
tcp 0 0 0.0.0.0:22122 0.0.0.0:* LISTEN 23275/fdfs_trackerd
7.配置及启动Storage Server
#/www/book_storage
#vim /etc/fdfs/storage.conf
# port=23000
base_path=/www/book_storage
#base_path,指定data和log所在目录,根目录必须存在,子目录会自动创建
store_path0=/www/book_storage
#文件的存储位置,在一台Storage Server上可以指定多个存储位置
group_name=group1
tracker_server=192.168.0.22:22122 #tracker_server 的ip
保存退出
启动storage server
#/etc/init.d/fdfs_storaged start
#netstat -antpul |grep 23000 或者lsof �Ci:23000 查看进程。
可以查看相关日志排错
#tail -f /www/book_storage/logs/storaged.log
验证验证上传下载
首先配置好客户端
#mkdir /www/book_client
#base_path=/www/book_client
tracker_server=192.168.0.22:22122
保存设置
测试上传
fdfs_test /etc/fdfs/client.conf upload /etc/fstab
This is FastDFS client test program v4.06
Copyright (C) 2008, Happy Fish / YuQing
FastDFS may be copied only under the terms of the GNU General
Public License V3, which may be found in the FastDFS source kit.
Please visit the FastDFS Home Page http://www.csource.org/
for more detail.
[2013-06-03 15:45:41] DEBUG - base_path=/www/book_client, connect_timeout=30, network_timeout=60, tracker_server_count=1, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0
tracker_query_storage_store_list_without_group:
server 1. group_name=, ip_addr=192.168.0.22, port=23000
group_name=group1, ip_addr=192.168.0.22, port=23000
storage_upload_by_filename
group_name=group1, remote_filename=M00/00/00/AQEBjFGsSaWAOjeUAAAD9M32Tdg9524157
source ip address: 192.168.0.22
file timestamp=2013-06-03 15:45:41
file size=1012
file crc32=3455471064
file url: http://192.168.0.22/group1/M00/00/00/AQEBjFGsSaWAOjeUAAAD9M32Tdg9524157
storage_upload_slave_by_filename
group_name=group1, remote_filename=M00/00/00/AQEBjFGsSaWAOjeUAAAD9M32Tdg9524157_big
source ip address: 192.168.0.22
file timestamp=2013-06-03 15:45:42
file size=1012
file crc32=3455471064
file url: http://192.168.0.22/group1/M00/00/00/AQEBjFGsSaWAOjeUAAAD9M32Tdg9524157_big
下载
#cd /usr/src
查看
# fdfs_file_info /etc/fdfs/client.conf group1/M00/00/00/AQEBjFGsSaWAOjeUAAAD9M32Tdg9524157_big
source storage id: 0
source ip address: 192.168.0.22
file create timestamp: 2013-06-03 15:45:42
file size: 1012
file crc32: 3455471064 (0xCDF64DD8)
# fdfs_download_file /etc/fdfs/client.conf group1/M00/00/00/AQEBjFGsSaWAOjeUAAAD9M32Tdg9524157_big
-rw-r--r-- 1 root root 1012 Jun 3 15:59 AQEBjFGsSaWAOjeUAAAD9M32Tdg9524157_big
删除
fdfs_delete_file /etc/fdfs/client.conf group1/M00/00/00/AQEBjFGsSaWAOjeUAAAD9M32Tdg9524157_big
8.Fdfs 和Nginx 的整合
8.1因为FastDFS默认自带的http服务器性能不好,所以一般建议用外置的apache或者nginx来解决http下载,以应付大并发的情况.
#cd /usr/src/
#wget http://fastdfs-nginx-module.googlecode.com/files/ fastdfs-nginx-module_v1.15.tar.gz
#wget http://nginx.org/download/nginx-1.3.9.tar.gz
#tar zxvf fastdfs-nginx-module_v1.15.tar.gz
#tar zxvf nginx-1.3.9.tar.gz
# apt-get install libssl-dev zlib1g-dev libpcre3-dev
# cd nginx-1.3.9/
#./configure --prefix=/usr/local/nginx --with-http_gzip_static_module --add-module=/usr/src/fastdfs-nginx-module/src/
#make && make install
8.2 修改相关配置文件
修改nginx扩展模块的配置文件
#cd ../usr/src/fastdfs-nginx-module/src
#cp mod_fastdfs.conf /etc/fdfs/
#vim /etc/fdfs/mod_fastdfs.conf
base_path=/www/logs
#存放log的路径
tracker_server=192.168.0.22:22122
#指定tracker服务器及端口
url_have_group_name = true
#这个很重要,在URL中包含group名称
store_path0=/www/book_storage
#存储文件的路径
storage_server_port=23000
#与storage的配置端口保持一致
保存后退出
!!!!!查看/www/logs目录是否存在
做M00的链接
sudo ln -s /www/book_storage/data /www/book_storage/data/M00
修改nginx的配置文件
#vim /usr/local/nginx/conf/nginx.conf
server {
listen 8888;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root /www/book_storage/data;
index index.html index.htm;
}
location /group1/M00 {
root /www/book_storage/data;
ngx_fastdfs_module;
}
保存退出
#cp /usr/local/nginx/sbin/nginx /etc/init.d/nginx
#/etc/init.d/nginx -t
ngx_http_fastdfs_set pid=23580
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
检查配置文件语法
#/etc/init.d/nginx ##启动nginx
检查端口
# lsof -i:8888
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 3770 root 6u IPv4 11231 0t0 TCP *:8888 (LISTEN)
nginx 3771 nobody 6u IPv4 11231 0t0 TCP *:8888 (LISTEN)
# netstat -antpul |grep tcp
tcp 0 0 0.0.0.0:22122 0.0.0.0:* LISTEN 23275/fdfs_trackerd
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 22917/nginx
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 2117/sshd
tcp 0 0 0.0.0.0:23000 0.0.0.0:* LISTEN 23325/fdfs_storaged
tcp 0 0 0.0.0.0:8888 0.0.0.0:* LISTEN 22917/nginx
tcp 0 0 192.168.0.22:22122 192.168.0.22:48515 ESTABLISHED 23275/fdfs_trackerd
tcp 0 0 192.168.0.22:22 1.1.1.24:1558 ESTABLISHED 16381/sshd: boo
tcp 0 0 192.168.0.22:48515 192.168.0.22:22122 ESTABLISHED 23325/fdfs_storaged
tcp6 0 0 :::22 :::* LISTEN 2117/sshd
测试上传和下载
#fdfs_test /etc/fdfs/client.conf upload /etc/fstab
#cd /usr/src
#wget http://192.168.0.22:8888/group1/M00/00/00/AQEBjFGsVESARdlrAAAD9M32Tdg0763076_big
--2013-06-03 16:32:40-- http://192.168.0.22:8888/group1/M00/00/00/AQEBjFGsVESARdlrAAAD9M32Tdg0763076_big
Connecting to 192.168.0.22:8888... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1012
Saving to: `AQEBjFGsVESARdlrAAAD9M32Tdg0763076_big'
100%[======================================================================================>] 1,012 --.-K/s in 0s
2013-06-03 16:32:40 (309 MB/s) - `AQEBjFGsVESARdlrAAAD9M32Tdg0763076_big' saved [1012/1012]
9.添加新的tracker server Storage Server同步设置
sudo vi /etc/fdfs/storage.conf
修改以下内容
sync_start_time=0:00
sync_end_time=23:59
#设置允许同步时间,设置的时候考虑避开业务高峰时段
tracker_server=:192.168.1.216:22122
tracker_server=192.168.1.217:22122
#这里我们举例192.168.1.216是原tracker_server,192.168.1.217是本身的tracker_server,只要添加原来的tracker_server就行,实际配置中,ip地址按实际需求来配置
保存后退出
如何查看并删除无效的storage server
#dfs_monitor /etc/fdfs/client.conf 可以查看当前group信息,以及一些统计信息。
再使用fdfs_monitor来删除。命令行如下:
fdfs_monitor delete
例如:
fdfs_monitor /etc/fdfs/client.conf delete group1 192.168.0.100