1. 程式人生 > >分布式文件系統FastDFS如何做到高可用

分布式文件系統FastDFS如何做到高可用

代碼 哪些 處理 多系統 fastdht 其中 rewrite 作用 高性能

FastDFS是用C語言編寫的一款開源的輕量級分布式文件系統。它對文件進行管理,功能包括:文件存儲、文件同步、文件訪問(文件上傳、文件下載)等,解決了大容量存儲和負載均衡的問題。特別適合以文件為載體的在線服務,如相冊網站、視頻網站等等。
FastDFS為互聯網量身定制,充分考慮了冗余備份、負載均衡、線性擴容等機制,並註重高可用、高性能等指標,使用FastDFS很容易搭建一套高性能的文件服務器集群提供文件上傳、下載等服務。

與Hadoop有什麽區別?

  Hadoop也是一個分布式文件系統,hadoop是處理大數據的,什麽是大數據呢?就是海量數據。海量數據你一塊磁盤估計存不下,那麽就需要把數據存到多個磁盤上,還得統一管理,這時就需要一個分布式文件系統來管理。FastDFS同樣也是這麽一個意思,圖片我們有很多,但容量有上限,所以我們要把這些所有的圖片存儲到多臺服務器上,還要進行統一管理,那麽就需要一個分布式文件系統,很顯然那就是FastDFS了,FastDFS適合於存取圖片(建議範圍:4KB < file_size <500MB)。

  FastDFS其實很早開始使用,但這次要作內訓,因此下面借鑒網友的部份內容結合實踐作總結,有些出處可能忘了 請多擔待。

FastDFS架構

  下面來看一張FastDFS的架構圖,如下圖所示。

  FastDFS架構包括Tracker server和Storage server。

  客戶端請求Tracker server進行文件上傳、下載,通過Tracker server調度最終由Storage server完成文件上傳和下載。Tracker server的作用是負載均衡和調度,通過Tracker server在文件上傳時可以根據一些策略找到Storage server提供文件上傳服務,可以將tracker稱為追蹤服務器或調度服務器。Tracker server跟蹤器和存儲節點都可以由一臺或多臺服務器構成,跟蹤器和存儲節點中的服務器均可以隨時增加或下線而不會影響線上服務,其中跟蹤器中的所有服務器都是對等的,可以根據服務器的壓力情況隨時增加或減少。Tracker負責管理所有的Storage和group,每個storage在啟動後會連接Tracker,告知自己所屬的group等信息,並保持周期性的心跳,tracker根據storage的心跳信息,建立group==>[storage server list]的映射表,Tracker需要管理的元信息很少,會全部存儲在內存中;另外tracker上的元信息都是由storage匯報的信息生成的,本身不需要持久化任何數據,這樣使得tracker非常容易擴展,直接增加tracker機器即可擴展為tracker cluster來服務,cluster裏每個tracker之間是完全對等的,所有的tracker都接受stroage的心跳信息,生成元數據信息來提供讀寫服務。

  Storage server作用是文件存儲,客戶端上傳的文件最終存儲在Storage服務器上,Storage server沒有實現自己的文件系統而是利用操作系統的文件系統來管理文件,可以將storage稱為存儲服務器。存儲系統由一個或多個組組成,組與組之間的文件是相互獨立的,所有組的文件容量累加就是整個存儲系統中的文件容量。一個卷[Volume](組[group])可以由一臺或多臺存儲服務器組成,一個組中的存儲服務器中的文件都是相同的,組中的多臺存儲服務器起到了冗余備份和負載均衡的作用,數據互為備份,存儲空間以group內容量最小的storage為準,所以建議group內的多個storage盡量配置相同,以免造成存儲空間的浪費。

技術分享圖片

  我們從上圖還能看到,Client端可以有多個,也就是同時支持多個客戶端對FastDFS集群服務進行訪問,Tracker是跟蹤器,負責協調Client與Storage之間的交互,為了實現高可用性,需要用多個Tracker來作為跟蹤器。Storage是專門用來存儲東西的,而且是分組進行存儲的,每一組可以有多臺設備,這幾臺設備存儲的內容完全一致,這樣做也是為了高可用性,當現有分組容量不夠時,我們可以水平擴容,即增加分組來達到擴容的目的。另外需要註意的一點是,如果一組中的設備容量大小不一致,比如設備A容量是80G,設備B的容量是100G,那麽這兩臺設備所在的組的容量會以小的容量為準,也就是說,當存儲的東西大小超過80G時,我們將無法存儲到該組中了。Client端在與Storage進行交互的時候也與Tracker cluster進行交互,說的通俗點就是Storage向Tracker cluster進行匯報登記,告訴Tracker現在自己哪些位置還空閑,剩余空間是多大。

文件上傳的流程

  現給出一張文件上傳的時序圖,如下圖所示:

技術分享圖片

  從中可以看到,Client想上傳圖片,它先向Tracker進行詢問,Tracker查看一下登記信息之後,告訴Client哪個storage當前空閑,Tracker會把IP和端口號都返回給Client,Client在拿到IP和端口號之後,便不再需要通過Tracker,直接便向Storage進行上傳圖片,Storage在保存圖片的同時,會向Tracker進行匯報,告訴Tracker它當前是否還留有剩余空間,以及剩余空間大小。匯報完之後,Storage將服務器上存儲圖片的地址返回給Client,Client可以拿著這個地址進行訪問圖片。說得更加細致一點,客戶端上傳文件後存儲服務器將文件ID返回給客戶端,此文件ID用於以後訪問該文件的索引信息。文件索引信息包括:組名,虛擬磁盤路徑,數據兩級目錄,文件名,如下所示:

技術分享圖片

組名:文件上傳後所在的storage組名稱,在文件上傳成功後由storage服務器返回,需要客戶端自行保存。
虛擬磁盤路徑:storage配置的虛擬路徑,與磁盤選項store_path*對應。如果配置了store_path0則是M00,如果配置了store_path1則是M01,以此類推。
數據兩級目錄:storage服務器在每個虛擬磁盤路徑下創建的兩級目錄,用於存儲數據文件。
文件名:與文件上傳時不同。是由存儲服務器根據特定信息生成,文件名包含:源存儲服務器IP地址、文件創建時間戳、文件大小、隨機數和文件拓展名等信息。

文件下載的流程

  現給出一張文件下載的時序圖,如下圖所示:

技術分享圖片

文件下載的步驟可以是:

1. client詢問tracker下載文件的storage,參數為文件標識(組名和文件名)。
2. tracker返回一臺可用的storage。
3. client直接和storage通訊完成文件下載。

搭建FastDFS

安裝組件

nginx+FastDFS+fastdfs-nginx-module

布署結構:
tracker:storage0:192.168.80.32
storage1:192.168.80.30
storage2:192.168.80.31

nginx 放在192.168.80.32

下載下列最新的安裝包:
fastdfs-master.zip:FastDFS源碼
libfastcommon-master.zip:(從 FastDFS 和 FastDHT 中提取出來的公共 C 函數庫)
fastdfs-nginx-module-master.zip:storage節點http服務nginx模塊
nginx.tar.gz:Nginx安裝包

防火墻

防火墻中打開tracker服務器端口( 默認為 22122)
shell> vi /etc/sysconfig/iptables
添加如下端口行:

-A INPUT -m state --state NEW -m tcp -p tcp --dport 22122 -j ACCEPT

storage服務器需要添加端口

-A INPUT -m state --state NEW -m tcp -p tcp --dport 23000 -j ACCEPT

重啟防火墻:
shell> service iptables restart

所有服務器先安裝libevent工具包

yum -y install libevent

所有服務器安裝libfastcommon工具包

先將fastdfs-master.zip和libfastcommon-master.zip 上傳至所有服務器的/opt文件夾下

1. 解壓縮 unzip libfastcommon-master.zip

編譯安裝
2. cd libfastcommon-master
3. ./make.sh
4. ./make.sh install
5. 把/usr/lib64/libfastcommon.so文件向/usr/lib/下復制一份 (32位才需要)

安裝Tracker服務

解壓縮unzip fastdfs-master.zip

編譯安裝

 cd fastdfs-master
 ./make.sh
./make.sh install

安裝後在/usr/bin/目錄下有以fdfs開頭的文件都是編譯出來的。
配置文件都放到/etc/fdfs文件夾
把/opt/fastdfs-master/conf目錄下的所有的配置文件都復制到/etc/fdfs下。

cp -r /opt/fastdfs-master/conf/* /etc/fdfs

創建文件存放路徑

mkdir -p /data/fastdfs/tracker #創建tracker文件存放路徑(tracker服務器才需要)
mkdir -p /data/fastdfs/storage #創建storage 文件存放路徑
mkdir -p /data/fastdfs/client #創建client 文件存放路徑

配置tracker服務

修改/etc/fdfs/conf/tracker.conf文件。

vim /etc/fdfs/tracker.conf #編輯tracker配置文件
bind_addr=  #綁定IP  綁定的IP地址 (常用於服務器有多個IP但只希望一個IP提供服務)。如果不填則表示所有的(一般不填就OK),相信較熟練的SA都常用到類似功能,很多系統和應用都有
port=22122     #tracker服務端口  
base_path=/data/fastdfs/tracker #目錄地址,裏面會創建data(存放存儲服務器信息)、logs,日誌文件  (根目錄必須存在,子目錄會自動創建)

其它內容默認,有關配置說明參考文章後面補充內容。

配置storage服務

在2臺storage服務器上配置storage服務,前題也是安裝libfastcommon和fastdfs。

修改/etc/fdfs/conf/storage.conf文件。

group_name=group1 #存儲組名
client_bind=true #當連接其他服務器時解析該主機地址
port=23000 #storage端口 23000
base_path=/data/fastdfs/storage #基礎存儲數據和日誌文件
store_path0=/data/fastdfs/storage #group 所占用的目錄或硬盤,有幾個寫幾個
tracker_server=192.168.80.32:22122 #指定tracker1服務器

其它內容默認,有關配置說明參考文章後面補充內容。

只編輯tracker服務器上的client.conf

vim /etc/fdfs/client.conf
base_path=/data/fastdfs/client  #基礎數據和日誌文件
tracker_server=192.168.80.32:22122 #tracker1服務器

以上就是fastdfs的所有配置,下面分別啟動32服務上的tracker、storage和30和31上的storage。

啟動tracker

/usr/bin/fdfs_trackerd  /etc/fdfs/tracker.conf

重啟使用命令:

/usr/bin/fdfs_trackerd  /etc/fdfs/tracker.conf  restart

檢查FastDFS Tracker Server是否啟動成功:
ps -ef | grep fdfs_trackerd

停止:

/etc/init.d/fdfs_trackerd stop
設置tracker服務開機啟動

chkconfig fdfs_trakcerd on

啟動storage服務

/usr/bin/fdfs_storaged  /etc/fdfs/storage.conf restart
停止storage服務器
 /etc/init.d/fdfs_storaged stop
設置storage服務開機啟動
chkconfig fdfs_storaged on

測試服務

/usr/bin/fdfs_test  /etc/fdfs/client.conf  upload   /etc/fdfs/anti-steal.jpg

技術分享圖片

有以上返回內容說明已經上傳成功,但我們將url 在瀏覽器上訪問時會返回404 是不允許直接訪問的,因此我們需要用到下面的nginx代理來作web服務訪問。

搭建nginx提供http服務

fastdfs-nginx-module 作用說明
  FastDFS 通過 Tracker 服務器,將文件放在 Storage 服務器存儲,但是同組存儲服務器之間需要進入文件復制,有同步延遲的問題。
  如果Tracker 服務器將文件上傳到了 192.168.80.30,上傳成功後文件ID已經返回給客戶端。此時 FastDFS 存儲集群機制會將這個文件同步到同組存儲192.168.80.31,在文件還沒有復制完成的情況下,客戶端如果用這個文件 ID 在 192.168.80.31 上取文件,就會出現文件無法訪問的錯誤。
  而 fastdfs-nginx-module 可以重定向文件連接到源服務器取文件,避免客戶端由於復制延遲導致的文件無法訪問錯誤
  可以使用官方提供的nginx插件。要使用nginx插件需要重新編譯。

更改fastdfs-nginx-module配置

上傳fastdfs-nginx-module.tar.gz
1. 解壓插件壓縮包
2. 修改/opt/fastdfs-nginx-module/src/config文件,把其中的local去掉。(最新的沒有local)

技術分享圖片

將mod_fastdfs.conf 拷貝到fdfs下進行配置

cd fastdfs-nginx-module/src
cp mod_fastdfs.conf /etc/fdfs/ #將mod_fastdfs.conf 拷貝到fdfs下進行配置

vim /etc/fdfs/mod_fastdfs.conf
base_path=/tmp #日誌存放路徑
tracker_server=192.168.80.32:22122 #配置成tracker server 地址和端口
storage_server_port=23000
url_have_group_name = true #url 中是否包組名
store_path0=/data/fastdfs/storage #文件存放路徑,與storage 一致
group_name=group1

編譯安裝Nginx

安裝依賴包

yum -y install zlib zlib-devel openssl openssl--devel pcre pcre-devel

安裝nginx

上傳解壓nginx

cd nginx

對nginx重新config
./configure --prefix=/opt/nginx --pid-path=/opt/nginx/nginx.pid --lock-path=/opt/nginx.lock --error-log-path=/opt/nginx/log/error.log --http-log-path=/opt/nginx/log/access.log --with-http_gzip_static_module --http-client-body-temp-path=/opt/nginx/client --http-proxy-temp-path=/opt/nginx/proxy --http-fastcgi-temp-path=/opt/nginx/fastcgi --http-uwsgi-temp-path=/opt/nginx/uwsgi --http-scgi-temp-path=/opt/nginx/scgi --add-module=/opt/fastdfs-nginx-module/src

再進行

./make.sh && ./make.sh install

配置nginx

vim /opt/nginx/conf/nginx.conf

在nginx的配置文件中添加一個Server:
server {
        listen       8888;
        server_name  192.168.80.32;

        location /group1/M00/{
                #root /home/FastDFS/fdfs_storage/data;
                ngx_fastdfs_module;
        }
}

但上面的內容已經固定死了group1的M00,Storage 對應有多個 group 的情況下,訪問路徑帶 group 名,如/group1/M00/00/00/xxx,在這裏改用:

location ~/group([0-9])/M00 {
  ngx_fastdfs_module;
}

註意:

8888 端口值是要與/etc/fdfs/storage.conf 中的http.server_port=8888 相對應,因為 http.server_port 默認為 8888,如果想改成 80,則要對應修改過來。

如查下載時如發現老報 404, 將 nginx.conf 第一行 user nobody 修改為 user root 後重新啟動。
防火墻中打開 Nginx 的 8888 端口
vi /etc/sysconfig/iptables
添加:
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8888 -j ACCEPT
重新啟動防火墻:
shell> service iptables restart

開機自啟動

即在rc.local增加啟動代碼就可以了。
vi /etc/rc.local
增加一行 /opt/nginx/sbin/nginx
設置執行權限:
chmod 755 rc.local

啟動Nginx

shell> /opt/nginx/sbin/nginx
ngx_http_fastdfs_set pid=xxx

nginx重啟命令為:

/opt/nginx/sbin/nginx -s reload

訪問測試圖片

  通過瀏覽器訪問測試時上傳的文件,測試上傳後返回的文件ID為:group1/M00/00/00/wKhQIFoKF3KAfw8wAABdrZgsqUU551_big.jpg,用瀏覽訪問的地址為:http://192.168.80.32:8888/group1/M00/00/00/wKhQIFoKF3KAfw8wAABdrZgsqUU551_big.jpg
註意: 千萬不要使用 kill -9 命令強殺 FastDFS 進程,否則可能會導致 binlog 數據丟失。

  至此已經搭起了一個簡單的集群模式,其中上面的配置需要根據實際情況進行調整。

說明:

tracker配置文件說明:

disabled=false#配置是否生效
bind_addr=192.168.6.102#綁定IP
port=22122#服務端口
connect_timeout=30#連接超時時間
network_timeout=60# tracker server的網絡超時,單位為秒。
base_path=/home/yangzi#目錄地址,裏面會創建data(存放存儲服務器信息)、logs,日誌文件
max_connections=256#系統提供服務最大連接數
work_threads=4#線程數,通常設置CPU數
store_lookup=2
上傳組(卷) 的方式 0:輪詢方式 1: 指定組 2: 平衡負載(選擇最大剩余空間的組(卷)上傳)
這裏如果在應用層指定了上傳到一個固定組,那麽這個參數被繞過
store_group=group1
當上一個參數設定為1 時 (store_lookup=1,即指定組名時),必須設置本參數為系統中存在的一個組名。如果選擇其他的上傳方式,這個參數就沒有效了
store_server=0
選擇哪個storage server 進行上傳操作(一個文件被上傳後,這個storage server就相當於這個文件的storage server源,會對同組的storage server推送這個文件達到同步效果)
# 0: 輪詢方式
# 1: 根據ip 地址進行排序選擇第一個服務器(IP地址最小者)
# 2: 根據優先級進行排序(上傳優先級由storage server來設置,參數名為upload_priority)
store_path=0
選擇storage server 中的哪個目錄進行上傳。storage server可以有多個存放文件的base path(可以理解為多個磁盤)。
# 0: 輪流方式,多個目錄依次存放文件
# 2: 選擇剩余空間最大的目錄存放文件(註意:剩余磁盤空間是動態的,因此存儲到的目錄或磁盤可能也是變化的)
download_server=0
 選擇哪個 storage server 作為下載服務器
# 0: 輪詢方式,可以下載當前文件的任一storage server
# 1: 哪個為源storage server 就用哪一個 (前面說過了這個storage server源 是怎樣產生的) 就是之前上傳到哪個storage server服務器就是哪個了
reserved_storage_space = 4GB
storage server 上保留的空間,保證系統或其他應用需求空間(指出 如果同組的服務器的硬盤大小一樣,以最小的為準,也就是只要同組中有一臺服務器達到這個標準了,這個標準就生效,原因就是因為他們進行備份)
log_level=info#選擇日誌級別
run_by_group=#操作系統運行FastDFS的用戶組
run_by_user=#操作系統運行FastDFS的用戶
allow_hosts=*#可以連接到此 tracker server 的ip範圍(對所有類型的連接都有影響,包括客戶端,storage server)
sync_log_buff_interval = 10# 同步或刷新日誌信息到硬盤的時間間隔,單位為秒
# 註意:tracker server 的日誌不是時時寫硬盤的,而是先寫內存。
check_active_interval = 120# 檢測 storage server 存活的時間隔,單位為秒。
# storage server定期向tracker server 發心跳,如果tracker server在一個check_active_interval內還沒有收到storage server的一次心跳,那邊將認為該storage server已經下線。所以本參數值必須大於storage server配置的心跳時間間隔。通常配置為storage server心跳時間間隔的2倍或3倍。
thread_stack_size = 64KB# 線程棧的大小。FastDFS server端采用了線程方式。更正一下,tracker server線程棧不應小於64KB,不是512KB。
# 線程棧越大,一個線程占用的系統資源就越多。如果要啟動更多的線程(V1.x對應的參數為max_connections,
V2.0為work_threads),可以適當降低本參數值。
storage_ip_changed_auto_adjust = true# 這個參數控制當storage server IP地址改變時,集群是否自動調整。註:只有在storage server進程重啟時才完成自動調整。
storage_sync_file_max_delay = 86400# V2.0引入的參數。存儲服務器之間同步文件的最大延遲時間,缺省為1天。根據實際情況進行調整
storage_sync_file_max_time = 300# V2.0引入的參數。存儲服務器同步一個文件需要消耗的最大時間,缺省為300s,即5分鐘。
http.disabled=true# HTTP服務是否不生效 當然編譯的時候我已經把 with_httpd宏去掉了,
http.server_port=80# HTTP服務端口
# 下列參數只有 開啟http服務才有用
http.check_alive_interval=30
http.check_alive_type=tcp
http.check_alive_uri=/status.html
http.need_find_content_type=true

storage.conf配置說明:

disabled=false#配置是否生效
group_name=group1#storage所在組(卷)
bind_addr=192.168.6.100# 綁定IP,另一太 storage IP為 192.168.6.101
client_bind=true#bind_addr通常是針對server的。當指定bind_addr時,本參數才有效。
port=23000# 是storage 服務端口
connect_timeout=30# 連接超時時間,針對socket套接字函數connect
network_timeout=60# storage server 網絡超時時間,單位為秒。
heart_beat_interval=30# 心跳間隔時間,單位為秒
stat_report_interval=60# storage server向tracker server報告磁盤剩余空間的時間間隔,單位為秒。
base_path=/home/eric# base_path 目錄地址,根目錄必須存在 子目錄會自動生成
# 會產生data(數據存儲地方)、 logs日誌文件
max_connections=256# 最大連接數
buff_size = 256KB# 設置隊列結點的buffer大小。
work_threads=4# 工作線程數
disk_rw_separated = true# 磁盤IO讀寫是否分離,缺省是分離的。
disk_reader_threads = 1# 針對單個存儲路徑的讀線程數,缺省值為1
disk_writer_threads = 1# 針對單個存儲路徑的寫線程數,缺省值為1
sync_wait_msec=200# 同步文件時,如果從binlog中沒有讀到要同步的文件,休眠N毫秒後重新讀取,0表示不休眠,立即再次嘗試讀取。
sync_interval=0# 同步上一個文件後,再同步下一個文件的時間間隔,單位為毫秒,0表示不休眠,直接同步下一個文件。
sync_start_time=00:00
sync_end_time=23:59# 允許系統同步的時間段 (默認是全天) 。一般用於避免高峰同步產生一些問題而設定,相信sa都會明白。
write_mark_file_freq=500# 把storage的mark文件定期同步到磁盤的時間間隔,單位為秒
store_path_count=1# 存放文件時storage server支持多個路徑(例如磁盤)。這裏配置存放文件的基路徑數目,通常只配一個目錄。
store_path0=/home/eric# 逐一配置store_path個路徑,索引號基於0。註意配置方法後面有0,1,2 ......,需要配置0到store_path - 1。
# 如果不配置base_path0,那邊它就和base_path對應的路徑一樣。
subdir_count_per_path=32# FastDFS存儲文件時,采用了兩級目錄。這裏配置存放文件的目錄個數
tracker_server=192.168.6.188:22122# tracker_server 的列表 要寫端口的哦
log_level=info# 日誌級別
run_by_group=# 運行storage 用戶組
run_by_user=# 運行storage 用戶
allow_hosts=*# 允許連接IP列表
file_distribute_path_mode=0
# 文件在data目錄下分散存儲策略。
# 0: 輪流存放
# 1: 隨機存儲
file_distribute_rotate_count=100# 當上面的參數file_distribute_path_mode配置為0(輪流存放方式)時,本參數有效。
#當一個目錄下的文件存放的文件數達到本參數值時,後續上傳的文件存儲到下一個目錄中
fsync_after_written_bytes=0# 當寫入大文件時,每寫入N個字節,調用一次系統函數fsync將內容強行同步到硬盤。0表示從不調用fsync
sync_log_buff_interval=10# 同步或刷新日誌信息到硬盤的時間間隔,單位為秒
sync_binlog_buff_interval=60# 同步binglog(更新操作日誌)到硬盤的時間間隔,單位為秒
sync_stat_file_interval=300# 把storage的stat文件同步到磁盤的時間間隔,單位為秒。
thread_stack_size=512KB# 線程棧的大小。FastDFS server端采用了線程方式。
# 線程棧越大,一個線程占用的系統資源就越多。
upload_priority=10
本storage server作為源服務器,上傳文件的優先級,可以為負數。值越小,優先級越高。這裏就和 tracker.conf 中store_server= 2時的配置相對應了
if_alias_prefix=
check_file_duplicate=0 # 是否檢測上傳文件已經存在。如果已經存在,則不存在文件內容,建立一個符號鏈接以節省磁盤空間。 結合 fastdfh使用的。 1是檢測,0是不檢測,我們不使用fastdfh 當然 0 
key_namespace=FastDFS# 當上個參數設定為1 或 yes時 (true/on也是可以的) , 在FastDHT中的命名空間
keep_alive=0# 與FastDHT servers 的連接方式 (是否為持久連接) 

# 下面是http的配置了就不多說了
http.disabled=true
http.domain_name=
http.server_port=80
http.trunk_size=256KB
http.need_find_content_type=true

問題:

編譯安裝nginx需要pcre包,未安裝會有如下提示:

技術分享圖片

./configure: error: the HTTP rewrite module requires the PCRE library.You can either disable the module by using --without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using --with-pcre=<path> option.

需要安裝pcre的devel包,pcre-devel。使用yum安裝即可:(以下命令還帶有ssl、zlib等依賴的安裝)

yum -y install zlib zlib-devel openssl openssl--devel pcre pcre-devel



分布式文件系統FastDFS如何做到高可用