分散式檔案系統FastDFS詳解

zwt9000發表於2018-01-08

上一篇文章《一次FastDFS併發問題的排查經歷》介紹了一次生產排查併發問題的經歷,可能有些人對FastDFS不是特別的瞭解,因此計劃寫幾篇文章完整的介紹一下這個軟體。

為什麼要使用分散式檔案系統呢?

嗯,這個問題問的好,使用了它對我們有哪些好處?帶著這個問題我們來往下看:

單機時代

初創時期由於時間緊迫,在各種資源有限的情況下,通常就直接在專案目錄下建立靜態資料夾,用於使用者存放專案中的檔案資源。如果按不同型別再細分,可以在專案目錄下再建立不同的子目錄來區分。例如:resources\static\fileresources\static\img等。

優點:這樣做比較便利,專案直接引用就行,實現起來也簡單,無需任何複雜技術,儲存資料庫記錄和訪問起來也很方便。

缺點:如果只是後臺系統的使用一般也不會有什麼問題,但是作為一個前端網站使用的話就會存在弊端。一方面,檔案和程式碼耦合在一起,檔案越多存放越混亂;另一方面,如果流量比較大,靜態檔案訪問會佔據一定的資源,影響正常業務進行,不利於網站快速發展。

獨立檔案伺服器

隨著公司業務不斷髮展,將程式碼和檔案放在同一伺服器的弊端就會越來越明顯。為了解決上面的問題引入獨立圖片伺服器,工作流程如下:專案上傳檔案時,首先通過ftp或者ssh將檔案上傳到圖片伺服器的某個目錄下,再通過ngnix或者apache來訪問此目錄下的檔案,返回一個獨立域名的圖片URL地址,前端使用檔案時就通過這個URL地址讀取。

優點:圖片訪問是很消耗伺服器資源的(因為會涉及到作業系統的上下文切換和磁碟I/O操作),分離出來後,Web/App伺服器可以更專注發揮動態處理的能力;獨立儲存,更方便做擴容、容災和資料遷移;方便做圖片訪問請求的負載均衡,方便應用各種快取策略(HTTP Header、Proxy Cache等),也更加方便遷移到CDN。

缺點:單機存在效能瓶頸,容災、垂直擴充套件性稍差

分散式檔案系統

通過獨立檔案伺服器可以解決一些問題,如果某天儲存檔案的那臺服務突然down了怎麼辦?可能你會說,定時將檔案系統備份,這臺down機的時候,迅速切換到另一臺就OK了,但是這樣處理需要人工來干預。另外,當儲存的檔案超過100T的時候怎麼辦?單臺伺服器的效能問題?這個時候我們就應該考慮分散式檔案系統了。

業務繼續發展,單臺伺服器儲存和響應也很快到達了瓶頸,新的業務需要檔案訪問具有高響應性、高可用性來支援系統。分散式檔案系統,一般分為三塊內容來配合,服務的儲存、訪問的仲裁系統,檔案儲存系統,檔案的容災系統來構成,仲裁系統相當於檔案伺服器的大腦,根據一定的演算法來決定檔案儲存的位置,檔案儲存系統負責儲存檔案,容災系統負責檔案系統和自己的相互備份。

優點:擴充套件能力: 毫無疑問,擴充套件能力是一個分散式檔案系統最重要的特點;高可用性: 在分散式檔案系統中,高可用性包含兩層,一是整個檔案系統的可用性,二是資料的完整和一致性;彈性儲存: 可以根據業務需要靈活地增加或縮減資料儲存以及增刪儲存池中的資源,而不需要中斷系統執行

缺點:系統複雜度稍高,需要更多伺服器

FastDFS

毫無疑問FastDFS就屬於我們上面介紹的分散式檔案系統,下面我們來詳細瞭解一下:

什麼是FastDFS

FastDFS是一個開源的輕量級分散式檔案系統。它解決了大資料量儲存和負載均衡等問題。特別適合以中小檔案(建議範圍:4KB < file_size <500MB)為載體的線上服務,如相簿網站、視訊網站等等。在UC基於FastDFS開發向使用者提供了:網盤,社群,廣告和應用下載等業務的儲存服務。

FastDFS是一款開源的輕量級分散式檔案系統純C實現,支援Linux、FreeBSD等UNIX系統類google FS,不是通用的檔案系統,只能通過專有API訪問,目前提供了C、Java和PHP API為網際網路應用量身定做,解決大容量檔案儲存問題,追求高效能和高擴充套件性FastDFS可以看做是基於檔案的key value pair儲存系統,稱作分散式檔案儲存服務更為合適。

FastDFS特性

  • 檔案不分塊儲存,上傳的檔案和OS檔案系統中的檔案一一對應
  • 支援相同內容的檔案只儲存一份,節約磁碟空間
  • 下載檔案支援HTTP協議,可以使用內建Web Server,也可以和其他Web Server配合使用
  • 支援線上擴容
  • 支援主從檔案
  • 儲存伺服器上可以儲存檔案屬性(meta-data)V2.0網路通訊採用libevent,支援大併發訪問,整體效能更好

FastDFS相關概念

FastDFS服務端有三個角色:跟蹤伺服器(tracker server)、儲存伺服器(storage server)和客戶端(client)。

tracker server:跟蹤伺服器,主要做排程工作,起負載均衡的作用。在記憶體中記錄叢集中所有儲存組和儲存伺服器的狀態資訊,是客戶端和資料伺服器互動的樞紐。相比GFS中的master更為精簡,不記錄檔案索引資訊,佔用的記憶體量很少。

Tracker是FastDFS的協調者,負責管理所有的storage server和group,每個storage在啟動後會連線Tracker,告知自己所屬的group等資訊,並保持週期性的心跳,tracker根據storage的心跳資訊,建立group==>[storage server list]的對映表。

Tracker需要管理的元資訊很少,會全部儲存在記憶體中;另外tracker上的元資訊都是由storage彙報的資訊生成的,本身不需要持久化任何資料,這樣使得tracker非常容易擴充套件,直接增加tracker機器即可擴充套件為tracker cluster來服務,cluster裡每個tracker之間是完全對等的,所有的tracker都接受stroage的心跳資訊,生成後設資料資訊來提供讀寫服務。

storage server:儲存伺服器(又稱:儲存節點或資料伺服器),檔案和檔案屬性(meta data)都儲存到儲存伺服器上。Storage server直接利用OS的檔案系統呼叫管理檔案。

Storage server(後簡稱storage)以組(卷,group或volume)為單位組織,一個group內包含多臺storage機器,資料互為備份,儲存空間以group內容量最小的storage為準,所以建議group內的多個storage儘量配置相同,以免造成儲存空間的浪費。

以group為單位組織儲存能方便的進行應用隔離、負載均衡、副本數定製(group內storage server數量即為該group的副本數),比如將不同應用資料存到不同的group就能隔離應用資料,同時還可根據應用的訪問特性來將應用分配到不同的group來做負載均衡;缺點是group的容量受單機儲存容量的限制,同時當group內有機器壞掉時,資料恢復只能依賴group內地其他機器,使得恢復時間會很長。

group內每個storage的儲存依賴於本地檔案系統,storage可配置多個資料儲存目錄,比如有10塊磁碟,分別掛載在/data/disk1-/data/disk10,則可將這10個目錄都配置為storage的資料儲存目錄。

storage接受到寫檔案請求時,會根據配置好的規則(後面會介紹),選擇其中一個儲存目錄來儲存檔案。為了避免單個目錄下的檔案數太多,在storage第一次啟動時,會在每個資料儲存目錄裡建立2級子目錄,每級256個,總共65536個檔案,新寫的檔案會以hash的方式被路由到其中某個子目錄下,然後將檔案資料直接作為一個本地檔案儲存到該目錄中。

client:客戶端,作為業務請求的發起方,通過專有介面,使用TCP/IP協議與跟蹤器伺服器或儲存節點進行資料互動。FastDFS向使用者提供基本檔案訪問介面,比如upload、download、append、delete等,以客戶端庫的方式提供給使用者使用。

另外兩個概念:

group :組, 也可稱為卷。 同組內伺服器上的檔案是完全相同的 ,同一組內的storage server之間是對等的, 檔案上傳、 刪除等操作可以在任意一臺storage server上進行 。

meta data :檔案相關屬性,鍵值對( Key Value Pair) 方式,如:width=1024,heigth=768 。

分散式檔案系統FastDFS詳解

Tracker相當於FastDFS的大腦,不論是上傳還是下載都是通過tracker來分配資源;客戶端一般可以使用ngnix等靜態伺服器來呼叫或者做一部分的快取;儲存伺服器內部分為卷(或者叫做組),卷於卷之間是平行的關係,可以根據資源的使用情況隨時增加,卷內伺服器檔案相互同步備份,以達到容災的目的。

上傳機制

首先客戶端請求Tracker服務獲取到儲存伺服器的ip地址和埠,然後客戶端根據返回的IP地址和埠號請求上傳檔案,儲存伺服器接收到請求後生產檔案,並且將檔案內容寫入磁碟並返回給客戶端file_id、路徑資訊、檔名等資訊,客戶端儲存相關資訊上傳完畢。

分散式檔案系統FastDFS詳解

內部機制如下:

1、選擇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優先

2、選擇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上配置)

3、選擇storage path

當分配好storage server後,客戶端將向storage傳送寫檔案請求,storage將會為檔案分配一個資料儲存目錄,支援如下規則:

  • 1、Round robin,多個儲存目錄間輪詢
  • 2、剩餘儲存空間最多的優先

4、生成Fileid

選定儲存目錄之後,storage會為檔案生一個Fileid,由storage server ip、檔案建立時間、檔案大小、檔案crc32和一個隨機數拼接而成,然後將這個二進位制串進行base64編碼,轉換為可列印的字串。 選擇兩級目錄 當選定儲存目錄之後,storage會為檔案分配一個fileid,每個儲存目錄下有兩級256*256的子目錄,storage會按檔案fileid進行兩次hash(猜測),路由到其中一個子目錄,然後將檔案以fileid為檔名儲存到該子目錄下。

5、生成檔名

當檔案儲存到某個子目錄後,即認為該檔案儲存成功,接下來會為該檔案生成一個檔名,檔名由group、儲存目錄、兩級子目錄、fileid、檔案字尾名(由客戶端指定,主要用於區分檔案型別)拼接而成。

下載機制

客戶端帶上檔名資訊請求Tracker服務獲取到儲存伺服器的ip地址和埠,然後客戶端根據返回的IP地址和埠號請求下載檔案,儲存伺服器接收到請求後返回檔案給客戶端。

分散式檔案系統FastDFS詳解

跟upload file一樣,在download file時客戶端可以選擇任意tracker server。tracker傳送download請求給某個tracker,必須帶上檔名資訊,tracke從檔名中解析出檔案的group、大小、建立時間等資訊,然後為該請求選擇一個storage用來服務讀請求。由於group內的檔案同步時在後臺非同步進行的,所以有可能出現在讀到時候,檔案還沒有同步到某些storage server上,為了儘量避免訪問到這樣的storage,tracker按照如下規則選擇group內可讀的storage。

  • 1、該檔案上傳到的源頭storage - 源頭storage只要存活著,肯定包含這個檔案,源頭的地址被編碼在檔名中。
  • 2、檔案建立時間戳==storage被同步到的時間戳 且(當前時間-檔案建立時間戳) > 檔案同步最大時間(如5分鐘) - 檔案建立後,認為經過最大同步時間後,肯定已經同步到其他storage了。
  • 3、檔案建立時間戳 < storage被同步到的時間戳。 - 同步時間戳之前的檔案確定已經同步了
  • 4、(當前時間-檔案建立時間戳) > 同步延遲閥值(如一天)。 - 經過同步延遲閾值時間,認為檔案肯定已經同步了。

同步時間管理

當一個檔案上傳成功後,客戶端馬上發起對該檔案下載請求(或刪除請求)時,tracker是如何選定一個適用的儲存伺服器呢? 其實每個儲存伺服器都需要定時將自身的資訊上報給tracker,這些資訊就包括了本地同步時間(即,同步到的最新檔案的時間戳)。而tracker根據各個儲存伺服器的上報情況,就能夠知道剛剛上傳的檔案,在該儲存組中是否已完成了同步。同步資訊上報如下圖:

分散式檔案系統FastDFS詳解

寫檔案時,客戶端將檔案寫至group內一個storage server即認為寫檔案成功,storage server寫完檔案後,會由後臺執行緒將檔案同步至同group內其他的storage server。

每個storage寫檔案後,同時會寫一份binlog,binlog裡不包含檔案資料,只包含檔名等元資訊,這份binlog用於後臺同步,storage會記錄向group內其他storage同步的進度,以便重啟後能接上次的進度繼續同步;進度以時間戳的方式進行記錄,所以最好能保證叢集內所有server的時鐘保持同步。

storage的同步進度會作為後設資料的一部分彙報到tracker上,tracke在選擇讀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生成一個同步時間戳。

精巧的檔案ID-FID

說到下載就不得不提檔案索引(又稱:FID)的精巧設計了。檔案索引結構如下圖,是客戶端上傳檔案後儲存伺服器返回給客戶端,用於以後訪問該檔案的索引資訊。檔案索引資訊包括:組名,虛擬磁碟路徑,資料兩級目錄,檔名。

分散式檔案系統FastDFS詳解

  • 組名:檔案上傳後所在的儲存組名稱,在檔案上傳成功後有儲存伺服器返回,需要客戶端自行儲存。
  • 虛擬磁碟路徑:儲存伺服器配置的虛擬路徑,與磁碟選項store_path*對應。
  • 資料兩級目錄:儲存伺服器在每個虛擬磁碟路徑下建立的兩級目錄,用於儲存資料檔案。
  • 檔名:與檔案上傳時不同。是由儲存伺服器根據特定資訊生成,檔名包含:源儲存伺服器IP地址、檔案建立時間戳、檔案大小、隨機數和檔案擴充名等資訊。

快速定位檔案

知道FastDFS FID的組成後,我們來看看FastDFS是如何通過這個精巧的FID定位到需要訪問的檔案。

  • 1、通過組名tracker能夠很快的定位到客戶端需要訪問的儲存伺服器組,並將選擇合適的儲存伺服器提供客戶端訪問;
  • 2、儲存伺服器根據“檔案儲存虛擬磁碟路徑”和“資料檔案兩級目錄”可以很快定位到檔案所在目錄,並根據檔名找到客戶端需要訪問的檔案。

分散式檔案系統FastDFS詳解

如何搭建FastDFS?參考我部落格的這篇文章FastDFS 叢集 安裝 配置 ,下圖為某使用者搭建的架構示意圖

分散式檔案系統FastDFS詳解

文中圖片均來源於網路

參考

官方網站
配置文件
Java客戶端
分散式檔案系統FastDFS設計原理
FASTDFS


喜歡我的文章,請關注我的公眾號

分散式檔案系統FastDFS詳解

相關文章