FastDFS簡介 && 架構原理 && 同步機制及解決 && 詳細安裝過程
1.簡介
FastDFS是用c語言編寫的一筐開源的分散式檔案系統,充分考慮了冗餘備份,負載均衡,線性擴容等機制,並注重高可用.高效能等指標,使用FastDFS可以很容易搭建一套高效能的檔案伺服器叢集提供檔案上傳下載.
2.FastDFS架構
FastDFS架構包括Tracker Server和Storage Server.客戶端請求Tracker Server進行檔案的上傳下載,通過Tracker Server排程最終由Storage Server完成檔案的上傳和下載;
- Tracker叢集
FastDFS叢集中的Tracker Server可以有多臺,Tracker Server之間是互相平等關係同事提供服務,不存在單點故障,客戶端向Tracker Server請求採用輪詢方式,
- Storage叢集
Storage叢集採用了分組儲存方式,storage叢集由一個或者多個組構成,叢集儲存的總容量就是所有組的儲存之和,一個組由多個儲存伺服器組成,組內的所有Storage Server之間是平等關係,會相互連線 進行檔案同步,從而保證組內的所有Storage Server的檔案內容一致,不同組之間的Storage Server之間不會相互通訊.
採用分組儲存的方式的好處是實現了冗餘備份,負載均衡,線性擴容的機制,當一個組的伺服器的訪問的壓力比較大 的時候可以在各組之內增加儲存伺服器來擴充服務能力(縱向擴容),當系統的容量不足時,可以增加組來擴充容量(橫向擴容)
3.檔案上傳流程
- 客戶端向Tracker Server 發出上傳檔案的請求
- Tracker Server根據Storage Server上傳的狀態報告查詢可用的Storage,返回這個Storage Server的ip:埠
- 客戶端拿著這個ip:埠去尋找Storage Server 進行上傳檔案,Storage Server將上傳的內容寫進磁碟中,之後返回個客戶端一個file_id 這個ID用於以後訪問檔案的索引資訊,檔案索引資訊包括:組名/虛擬吸盤路徑/資料兩級目錄/檔名
4.檔案下載流程
- 客戶端向Tracker Server發起下載檔案請求
- Tracker Server檢驗同步狀態,查出可用的Storage Server,返回給這個Storage Server的ip:埠
- 客戶端帶著Ip:埠和當時上傳這個檔案時給的File_id去找這個Storage Server
- Storage Server根據file_id查詢這個檔案返回給客戶端
5.FastDFS的同步機制和同步延遲的解決
- 檔案同步延遲問題
FastDFS同組中的Storage Server的資料是同步的,Storage Server對組內除自己以外的每臺伺服器都會啟動專門的執行緒根據binlog進行檔案同步,binlog中只記錄檔名,不記錄檔案內容.當組內新加入一臺伺服器時,由已有的一臺Storage Server將己有的所有資料(包括源頭資料和備份資料)全部同步給這臺新伺服器.檔案上傳至組內的一臺Storage Server後再由這臺Storage Server根據binlog同步給組內的其他伺服器這種同步的方式為非同步方式,非同步方式帶來了檔案同步延遲的問題,新檔案上傳之後,在汕尾被同步過去的Storage serVer中下載該檔案的時候就會出現檔案找不到的現象
- FastDFS對檔案同步延遲問題的解決
首先要知道的是,一個組中包含哪些Storage Server不是通過配置檔案設定的,而是通過Tracker Server獲取到的,Storage Server會啟動一個單獨的執行緒完成對一臺Tracker Server的連線和定時報告, Storage Server主動向Tracker Server報告其狀態資訊,包括磁碟剩餘空間,檔案同步狀況,檔案上傳下載次數等統計資訊,另外,每臺Storage Server都會定時向Tracker Server報告它向同組其他機器同步到的檔案時間戳.當Tracker Server收到一臺Storage Server發來的同步報告之後,他會依次找出該組中各個Storage Server被同步到的檔案時間戳最小值,作為Storage Server的一個屬性記錄到記憶體中,根據上述情況FastDFS提供下面簡單的解決方案:
- 當客戶端請求下載檔案時,優先選擇源Storage Server下載檔案即可,這可以在Tracker Server的配置檔案中進行設定,對應的引數名為download_server
- 選擇Storage Server的方式是輪流選擇,當客戶端詢問Tracker Server有哪些Storage Server可以下載指定檔案時,Tracker Server返回滿足如下的四個條件之一
a.該檔案上傳到的源Storage Server,檔案直接上傳到該伺服器上的
b.檔案建立時間戳 < Storage Server被同步到的檔案時間戳.這意味著當前檔案已經被同步過來了
c.檔案建立時間戳 = Storage Server 被同步到的檔案時間戳 並且 (當前時間-檔案建立時間戳) > 一個檔案同步需要完成需要的最大時間
d.(當前時間-檔案建立時間) > 檔案同步延遲閾值,比如我們把閾值設定為一條,代表檔案在一天之內肯定能完成同步
簡而言之:就是所有的Storage Server都會向Stracker Server提交自己的狀態資訊和檔案同步資訊,當客戶端來想Tracker發起下載請求時,Tracker Server會根據Storage Server提供的資訊一定會返回給客戶端一個 一定有完成同步的Storage Server的地址
6 FastDFS+Nginx實現檔案伺服器
6.1 FastDFS--tracker安裝
6.1.1 下載
tracker和storage使用相同的安裝包
下載地址:http://sourceforge.net/projects/FastDFS/ 或https://github.com/happyfish100/FastDFS(推薦
本教程下載:FastDFS_v5.05.tar.gz
6.1.2 FastDFS安裝環境
FastDFS是C語言開發,建議在linux上執行,本教程使用Centos6.4作為安裝環境。
安裝FastDFS需要先將官網下載的原始碼進行編譯,編譯依賴gcc環境,如果沒有gcc環境,需要安裝gcc:yum install gcc-c++
6.1.3 安裝libevent
FastDFS依賴libevent庫,需要安裝:
yum -y install libevent
6.1.4 安裝libfastcommon
libfastcommon是FastDFS官方提供的,libfastcommon包含了FastDFS執行所需要的一些基礎庫。
將libfastcommonV1.0.7.tar.gz拷貝至/usr/local/下
cd /usr/local
tar -zxvf libfastcommonV1.0.7.tar.gz
cd libfastcommon-1.0.7
./make.sh
./make.sh install
注意:libfastcommon安裝好後會自動將庫檔案拷貝至/usr/lib64下,由於FastDFS程式引用usr/lib目錄所以需要將/usr/lib64下的庫檔案拷貝至/usr/lib下。
要拷貝的檔案如下:
6.1.5 tracker編譯安裝
將FastDFS_v5.05.tar.gz拷貝至/usr/local/下
tar -zxvf FastDFS_v5.05.tar.gz
cd FastDFS
./make.sh
./make.sh install
安裝成功將安裝目錄下的conf下的檔案拷貝到/etc/fdfs/下。
6.1.6 配置
安裝成功後進入/etc/fdfs目錄:
拷貝一份新的tracker配置檔案:
cp tracker.conf.sample tracker.conf
修改tracker.conf
vi tracker.conf
base_path=/home/yuqing/FastDFS
改為:
base_path=/home/FastDFS
6.1.7 啟動
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart
啟動的日誌顯示先停止5619程序(實際環境不是5619)再啟動,如下圖:
注意:如果沒有顯示上圖要注意是否正常停止原有程序。
- 設定開機自動啟動。
[[email protected] FastDFS]# vim /etc/rc.d/rc.local |
將執行命令列新增進檔案:/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart
6.2 FastDFS--storage安裝
6.2.1 安裝libevent
同tracker安裝
6.2.2 安裝libfastcommon
同tracker安裝。
6.2.3 storage編譯安裝
同tracker編譯安裝。
6.2.4 配置
安裝成功後進入/etc/fdfs目錄:
拷貝一份新的storage配置檔案:
cp storage.conf.sample storage.conf
修改storage.conf
vi storage.conf
group_name=group1
base_path=/home/yuqing/FastDFS改為:base_path=/home/FastDFS
store_path0=/home/yuqing/FastDFS改為:store_path0=/home/FastDFS/fdfs_storage
#如果有多個掛載磁碟則定義多個store_path,如下
#store_path1=.....
#store_path2=......
tracker_server=192.168.101.3:22122 #配置tracker伺服器:IP
#如果有多個則配置多個tracker
tracker_server=192.168.101.4:22122
6.2.5 啟動
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart
啟動的日誌顯示先停止8931程序(實際環境不是8931)再啟動,如下圖:
注意:如果沒有顯示上圖要注意是否正常停止原有程序。
- 設定開機自動啟動。
[[email protected] FastDFS]# vim /etc/rc.d/rc.local |
將執行命令列新增進檔案:/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart
6.3 上傳圖片測試
6.3.1 通過Fast_test測試
FastDFS安裝成功可通過/usr/bin/fdfs_test測試上傳、下載等操作。
修改/etc/fdfs/client.conf
base_path=/home/fastdfs
tracker_server=192.168.101.3:22122
使用格式:
/usr/bin/fdfs_test 客戶端配置檔案地址 upload 上傳檔案
比如將/home下的圖片上傳到FastDFS中:
/usr/bin/fdfs_test /etc/fdfs/client.conf upload /home/tomcat.png
http://192.168.101.3/group1/M00/00/00/wKhlBVVY2M-AM_9DAAAT7-0xdqM485_big.png就是檔案的下載路徑。
對應storage伺服器上的
/home/fastdfs/fdfs_storage/data/00/00/wKhlBVVY2M-AM_9DAAAT7-0xdqM485_big.png檔案。
由於現在還沒有和nginx整合無法使用http下載。
6.3.2 通過java Client API
完整的測試方法參考測試原始碼。
public class FastdfsClientTest {
//客戶端配置檔案
public String conf_filename = "F:\\workspace_indigo\\fastdfsClient\\src\\cn\\itcast\\fastdfs\\cliennt\\fdfs_client.conf";
//本地檔案,要上傳的檔案
public String local_filename = "F:\\develop\\upload\\linshiyaopinxinxi_20140423193847.xlsx";
//上傳檔案
@Test
public void testUpload() {
for(int i=0;i<100;i++){
try {
ClientGlobal.init(conf_filename);
TrackerClient tracker = new TrackerClient();
TrackerServer trackerServer = tracker.getConnection();
StorageServer storageServer = null;
StorageClient storageClient = new StorageClient(trackerServer,
storageServer);
NameValuePair nvp [] = new NameValuePair[]{
new NameValuePair("item_id", "100010"),
new NameValuePair("width", "80"),
new NameValuePair("height", "90")
};
String fileIds[] = storageClient.upload_file(local_filename, null,
nvp);
System.out.println(fileIds.length);
System.out.println("組名:" + fileIds[0]);
System.out.println("路徑: " + fileIds[1]);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
6.4 FastDFS和Nginx整合
6.4.1 在Tracker上安裝nginx
nginx的安裝細節參考nginx文件。
在每個tracker上安裝nginx,的主要目的是做負載均衡及實現高可用。如果只有一臺tracker伺服器可以不配置nginx
6.4.2 在Storage 上安裝Nginx
6.4.2.1 FastDFS-nginx-module
將FastDFS-nginx-module_v1.16.tar.gz傳至/usr/local/下
cd /usr/local
tar -zxvf FastDFS-nginx-module_v1.16.tar.gz
cd FastDFS-nginx-module/src
修改config檔案將/usr/local/路徑改為/usr/
將FastDFS-nginx-module/src下的mod_FastDFS.conf拷貝至/etc/fdfs/下
cp mod_FastDFS.conf /etc/fdfs/
並修改mod_FastDFS.conf的內容:
vi /etc/fdfs/mod_FastDFS.conf
base_path=/home/FastDFS
tracker_server=192.168.101.3:22122
#tracker_server=192.168.101.4:22122(多個tracker配置多行)
url_have_group_name=true #url中包含group名稱
store_path0=/home/FastDFS/fdfs_storage #指定檔案儲存路徑
將libfdfsclient.so拷貝至/usr/lib下
cp /usr/lib64/libfdfsclient.so /usr/lib/
建立nginx/client目錄
mkdir -p /var/temp/nginx/client
6.4.2.2 nginx安裝
新增FastDFS-nginx-module模組
./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
make
make install
6.4.2.3 nginx配置檔案
新建一個nginx配置檔案nginx-fdfs.conf.
新增server:
server {
listen 80;
server_name 192.168.101.3;
location /group1/M00/{
#root /home/FastDFS/fdfs_storage/data;
ngx_fastdfs_module;
}
}
說明:
server_name指定本機ip
location /group1/M00/:group1為nginx 服務FastDFS的分組名稱,M00是FastDFS自動生成編號,對應store_path0=/home/FastDFS/fdfs_storage,如果FastDFS定義store_path1,這裡就是M01
6.4.3 測試
通過java客戶端上傳檔案,使用瀏覽器訪問,比如訪問上傳圖片測試的檔案:
訪問storage:
http://192.168.101.3/group1/M00/00/00/wKhlBVVY2M-AM_9DAAAT7-0xdqM485_big.png
6.5 附錄
6.5.1 tracker.conf
1 基本配置
disable
#func:配置是否生效
#valu:true、false
disable=false
bind_addr
#func:繫結IP
#valu:IP地址
bind_addr=192.168.6.102
port
#func:服務埠
#valu:埠整數值
port=22122
connect_timeout
#func:連線超時
#valu:秒單位正整數值
connect_timeout=30
network_timeout
#func:網路超時
#valu:秒單位正整數值
network_timeout=60
base_path
#func:Tracker資料/日誌目錄地址
#valu:路徑
base_path=/home/michael/fdfs/base4tracker
max_connections
#func:最大連線數
#valu:正整數值
max_connections=256
work_threads
#func:執行緒數,通常設定CPU數
#valu:正整數值
work_threads=4
store_lookup
#func:上傳檔案的選組方式。
#valu:0、1或2。
# 0:表示輪詢
# 1:表示指定組
# 2:表示儲存負載均衡(選擇剩餘空間最大的組)
store_lookup=2
store_group
#func:指定上傳的組,如果在應用層指定了具體的組,那麼這個引數將不會起效。另外如果store_lookup如果是0或2,則此引數無效。
#valu:group1等
store_group=group1
store_server
#func:上傳伺服器的選擇方式。(一個檔案被上傳後,這個storage server就相當於這個檔案的storage server源,會對同組的storage server推送這個檔案達到同步效果)
#valu:0、1或2
# 0: 輪詢方式(預設)
# 1: 根據ip 地址進行排序選擇第一個伺服器(IP地址最小者)
# 2: 根據優先順序進行排序(上傳優先順序由storage server來設定,引數名為upload_priority),優先順序值越小優先順序越高。
store_server=0
store_path
#func:上傳路徑的選擇方式。storage server可以有多個存放檔案的base path(可以理解為多個磁碟)。
#valu:
# 0: 輪流方式,多個目錄依次存放檔案
# 2: 儲存負載均衡。選擇剩餘空間最大的目錄存放檔案(注意:剩餘磁碟空間是動態的,因此儲存到的目錄或磁碟可能也是變化的)
store_path=0
download_server
#func:下載伺服器的選擇方式。
#valu:
# 0:輪詢(預設)
# 1:IP最小者
# 2:優先順序排序(值最小的,優先順序最高。)
download_server=0
reserved_storage_space
#func:保留空間值。如果某個組中的某個伺服器的剩餘自由空間小於設定值,則檔案不會被上傳到這個組。
#valu:
# G or g for gigabyte
# M or m for megabyte
# K or k for kilobyte
reserved_storage_space=1GB
log_level
#func:日誌級別
#valu:
# emerg for emergency
# alert
# crit for critical
# error
# warn for warning
# notice
# info for information
# debug for debugging
log_level=info
run_by_group / run_by_user
#func:指定執行該程式的使用者組
#valu:使用者組名或空
run_by_group=
#func:
#valu:
run_by_user=
allow_hosts
#func:可以連線到tracker server的ip範圍。可設定多個值。
#valu
allow_hosts=
check_active_interval
#func:檢測 storage server 存活的時間隔,單位為秒。
# storage server定期向tracker server 發心跳,
# 如果tracker server在一個check_active_interval內還沒有收到storage server的一次心跳,
# 那邊將認為該storage server已經下線。所以本引數值必須大於storage server配置的心跳時間間隔。
# 通常配置為storage server心跳時間間隔的2倍或3倍。
check_active_interval=120
thread_stack_size
#func:設定執行緒棧的大小。 執行緒棧越大,一個執行緒佔用的系統資源就越多。
# 如果要啟動更多的執行緒(V1.x對應的引數為max_connections,V2.0為work_threads),可以適當降低本引數值。
#valu:如64KB,預設值為64,tracker server執行緒棧不應小於64KB
thread_stack_size=64KB
storage_ip_changed_auto_adjust
#func:這個引數控制當storage server IP地址改變時,叢集是否自動調整。注:只有在storage server程序重啟時才完成自動調整。
#valu:true或false
storage_ip_changed_auto_adjust=true
2 同步
storage_sync_file_max_delay
#func:同組storage伺服器之間同步的最大延遲時間。儲存伺服器之間同步檔案的最大延遲時間,根據實際情況進行調整
#valu:秒為單位,預設值為1天(24*3600)
#sinc:v2.0
storage_sync_file_max_delay=86400
storage_sync_file_max_time
#func:儲存伺服器同步一個檔案需要消耗的最大時間,預設為300s,即5分鐘。
#sinc:v2.0
storage_sync_file_max_time=300
sync_log_buff_interval
#func:同步或重新整理日誌資訊到硬碟的時間間隔。注意:tracker server 的日誌不是時時寫硬碟的,而是先寫記憶體。
#valu:以秒為單位
sync_log_buff_interval=10
3 trunk 和 slot
#func:是否使用trunk檔案來儲存幾個小檔案
#valu:true或false
#sinc:v3.0
use_trunk_file=false
#func:最小slot大小
#valu:<= 4KB,預設為256位元組
#sinc:v3.0
slot_min_size=256
#func:最大slot大小
#valu:>= slot_min_size,當小於這個值的時候就儲存到trunk file中。預設為16MB。
#sinc:v3.0
slot_max_size=16MB
#func:trunk file的size
#valu:>= 4MB,預設為64MB
#sinc:v3.0
trunk_file_size=64MB
4 HTTP 相關
是否啟用 HTTP
#func:HTTP是否生效
#valu:true或false
http.disabled=false
HTTP 伺服器埠號
#func:tracker server上的http port
#valu:
#note:只有http.disabled=false時才生效
http.server_port=7271
檢查Storage存活狀態的間隔時間(心跳檢測)
#func:檢查storage http server存活的間隔時間
#valu:單位為秒
#note:只有http.disabled=false時才生效
http.check_alive_interval=30
心跳檢測使用的協議方式
#func:檢查storage http server存活的方式
#valu:
# tcp:連線到storage server的http埠,不進行request和response。
# http:storage check alive url must return http status 200.
#note:只有http.disabled=false時才生效
http.check_alive_type=tcp
檢查 Storage 狀態的 URI
#func:檢查storage http server是否alive的uri/url
#note:只有http.disabled=false時才生效
http.check_alive_uri=/status.html