FastDFS向使用者提供基本文件訪問接口,好比upload、download、append、delete等,以客戶端庫的方式提供給用戶使用。前端
選擇tracker servernginx
當集羣中不止一個tracker server時,因爲tracker之間是徹底對等的關係,客戶端在upload文件時能夠任意選擇一個trakcer。複製代碼
選擇存儲的groupapache
當tracker接收到upload file的請求時,會爲該文件分配一個能夠存儲該文件的group,支持以下選擇group的規則:bash
- Round robin,全部的group間輪詢
- Specified group,指定某一個肯定的group
- Load balance,剩餘存儲空間多多group優先
選擇storage serverapp
當選定group後,tracker會在group內選擇一個storage server給客戶端,支持以下選擇storage的規則:負載均衡
- Round robin,在group內的全部storage間輪詢
- First server ordered by ip,按ip排序
- First server ordered by priority,按優先級排序(優先級在storage上配置)
選擇storage path異步
當分配好storage server後,客戶端將向storage發送寫文件請求,storage將會爲文件分配一個數據存儲目錄,支持以下規則:編碼
- Round robin,多個存儲目錄間輪詢
- 剩餘存儲空間最多的優先
生成Fileidspa
選定存儲目錄以後,storage會爲文件生一個Fileid,由storage server ip、文件建立時間、文件大小、文件crc32和一個隨機數拼接而成,而後將這個二進制串進行base64編碼,轉換爲可打印的字符串。線程
選擇兩級目錄
當選定存儲目錄以後,storage會爲文件分配一個fileid,每一個存儲目錄下有兩級256*256的子目錄,storage會按文件fileid進行兩次hash(猜想),路由到其中一個子目錄,而後將文件以fileid爲文件名存儲到該子目錄下。
生成文件名
當文件存儲到某個子目錄後,即認爲該文件存儲成功,接下來會爲該文件生成一個文件名,文件名由group、存儲目錄、兩級子目錄、fileid、文件後綴名(由客戶端指定,主要用於區分文件類型)拼接而成。
文件上傳類型有3種:
1)upload:上傳普通文件,包括主文件
2)upload_appender:上傳appender文件,後續能夠對其進行append操做【又用做斷點續傳】
3)upload_slave:上傳從文件。
客戶端upload file成功後,會拿到一個storage生成的文件名,接下來客戶端根據這個文件名便可訪問到該文件。
跟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(當前時間-文件建立時間戳)>同步延遲閥值(如一天)。 -通過同步延遲閾值時間,認爲文件確定已經同步了。
Storage上的Nginx Module首先會去看本機有沒有被請求的文件,若是沒有的話,會從FileId中解開源Storage的IP地址,而後去訪問,若是此時源Storage當機了,那麼本次下載請求就此失敗(Nginx Module從始至終沒有拿着被請求文件的Group Name去問Tracker如今哪臺活着的Storage能響應請求)
因爲以上的流程沒法保證HA,因此咱們仍是決定在前端負載均衡設備上手動根據URL中的GroupName將請求轉到相應的upstream組(Storage Server組)中,惟一的很差是,增長Group時須要調整負載均衡設備的設置
刪除處理流程與文件下載類是:
寫文件時,客戶端將文件寫至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生成一個同步時間戳。
提供appender file的支持,經過upload_appender_file接口存儲,appender file容許在建立後,對該文件進行append操做。實際上,appender file與普通文件的存儲方式是相同的,不一樣的是,appender file不能被合併存儲到trunk file。.續傳涉及到的文件大小MD5不會改變。續傳流程與文件上傳類是,先定位到源storage,完成完整或部分上傳,再經過binlog進行同group內server文件同步。
FastDFS提供了設置/獲取文件擴展屬性的接口(setmeta/getmeta),擴展屬性以key-value對的方式存儲在storage上的同名文件(擁有特殊的前綴或後綴),好比/group/M00/00/01/some_file爲原始文件,則該文件的擴展屬性存儲在/group/M00/00/01/.some_file.meta文件(真實狀況不必定是這樣,但機制相似),這樣根據文件名就能定位到存儲擴展屬性的文件。
以上兩個接口做者不建議使用,額外的meta文件會進一步「放大」海量小文件存儲問題,同時因爲meta很是小,其存儲空間利用率也不高,好比100bytes的meta文件也須要佔用4K(block_size)的存儲空間。
FastDFS的tracker和storage都內置了http協議的支持,客戶端能夠經過http協議來下載文件,tracker在接收到請求時,經過http的redirect機制將請求重定向至文件所在的storage上;除了內置的http協議外,FastDFS還提供了經過apache或nginx擴展模塊下載文件的支持。