常見開源分散式檔案系統架構對比

JuiceFS發表於2022-04-24

什麼是檔案系統?

檔案系統是計算機中一個非常重要的元件,為儲存裝置提供一致的訪問和管理方式。在不同的作業系統中,檔案系統會有一些差別,但也有一些共性幾十年都沒怎麼變化:

  1. 資料是以檔案的形式存在,提供 Open、Read、Write、Seek、Close 等API 進行訪問;
  2. 檔案以樹形目錄進行組織,提供原子的重新命名(Rename)操作改變檔案或者目錄的位置。

檔案系統提供的訪問和管理方法支撐了絕大部分的計算機應用,Unix 的“萬物皆檔案”的理念更是凸顯了它的重要地位。檔案系統的複雜性使得它的可擴充套件性未能跟得上網際網路的高速發展,極大簡化了的物件儲存及時填補了空缺得以快速發展起來。因為物件儲存缺乏樹狀結構也不支援原子重新命名操作,跟檔案系統有很大的差別,本文暫不討論。

單機檔案系統的挑戰

絕大多數檔案系統都是單機的,在單機作業系統內為一個或者多個儲存裝置提供訪問和管理。隨著網際網路的高速發展,單機檔案系統面臨很多的挑戰:

  • 共享:無法同時為分佈在多個機器中的應用提供訪問,於是有了 NFS 協議,可以將單機檔案系統通過網路的方式同時提供給多個機器訪問。
  • 容量:無法提供足夠空間來儲存資料,資料只好分散在多個隔離的單機檔案系統裡。
  • 效能:無法滿足某些應用需要非常高的讀寫效能要求,應用只好做邏輯拆分同時讀寫多個檔案系統。
  • 可靠性:受限於單個機器的可靠性,機器故障可能導致資料丟失。
  • 可用性:受限於單個作業系統的可用性,故障或者重啟等運維操作會導致不可用。

隨著網際網路的高速發展,這些問題變得日益突出,湧現出了一些分散式檔案系統來應對這些挑戰。

下面介紹幾個我瞭解過的分散式檔案系統的基本架構,並比較不同架構的優點和侷限。

GlusterFS

GlusterFS 是由美國的 Gluster 公司開發的 POSIX 分散式檔案系統(以 GPL 開源),2007年釋出第一個公開版本,2011年被 Redhat 收購。

它的基本思路就是通過一個無狀態的中介軟體把多個單機檔案系統融合成統一的名字空間(namespace)提供給使用者。這個中介軟體是由一系列可疊加的轉換器(Translator)實現,每個轉換器解決一個問題,比如資料分佈、複製、拆分、快取、鎖等等,使用者可以根據具體的應用場景需要靈活配置。比如一個典型的分散式卷如下圖所示:

image.png

Server1 和 Server2 構成有 2 副本的 Volume0,Server3 和 Server4 構成 Volume1,它們再融合成有更大空間的分散式卷。

優點
資料檔案最終以相同的目錄結構儲存在單機檔案系統上,不用擔心 GlusterFS 的不可用導致資料丟失。

沒有明顯的單點問題,可線性擴充套件。

對大量小檔案的支援估計還不錯。

挑戰
這種結構是相對靜態的,不容易調整,也要求各個儲存節點有相同的配置,當資料或者訪問不均衡時沒法進行空間或者負載調整。故障恢復能力也比較弱,比如 Server1 故障時,Server2 上的檔案就沒辦法在健康的 3 或者 4上增加拷貝保障資料可靠。

因為缺乏獨立的後設資料服務,要求所有儲存節點都會有完整的資料目錄結構,遍歷目錄或者做目錄結構調整時需要訪問所有節點才能得到正確結果,導致整個系統的可擴充套件能力有限,擴充套件到幾十個節點時還行,很難有效地管理上百個節點。

CephFS

CephFS 始於 Sage Weil 的博士論文研究,目標是實現分散式的後設資料管理以支援 EB 級別資料規模。2012年,Sage Weil 成立了 InkTank 繼續支援 CephFS 的開發,於 2014年被 Redhat 收購。直到 2016 年,CephFS 才釋出可用於生產環境的穩定版(CephFS 的後設資料部分仍然是單機的)。現在,CephFS 的分散式後設資料仍然不成熟。

Ceph 是一個分層的架構,底層是一個基於 CRUSH(雜湊)的分散式物件儲存,上層提供物件儲存(RADOSGW)、塊儲存(RDB)和檔案系統(CephFS)三個API,如下圖所示:

image.png

用一套儲存系統來滿足多個不同場景的儲存需求(虛擬機器映象、海量小檔案和通用檔案儲存)還是非常吸引人的,但因為系統的複雜性需要很強的運維能力才能支撐,實際上目前只有塊儲存還是比較成熟應用得比較多,物件儲存和檔案系統都不太理想,聽到一些使用案例用過一段時間後就放棄了。

CephFS 的架構如下圖所示:

image.png

CephFS 是由 MDS(Metadata Daemon) 實現的,它是一個或者多個無狀態的後設資料服務,從底層的 OSD 載入檔案系統的元資訊,並快取到記憶體中以提高訪問速度。因為 MDS 是無狀態的,可以配置多個備用節點來實現 HA,相對比較容易。不過備份節點沒有快取,需要重新預熱,有可能故障恢復時間會比較長。

因為從儲存層載入或者寫入資料會比較慢,MDS 必須使用多執行緒來提高吞吐量,各種併發的檔案系統操作導致複雜度大大上升,容易發生死鎖,或者因為 IO 比較慢導致的效能大幅下降。為了獲得比較好的效能,MDS 往往需要有足夠多的記憶體來快取大部分後設資料,這也限制了它實際的支撐能力。

當有多個活躍的 MDS 時,目錄結構中的一部分(子樹)可以動態的分配到某個MDS並完全由它來處理相關請求,以達到水平擴充套件的目的。多個活躍之前,不可避免地需要各自鎖機制來協商對子樹的所有權,以及通過分散式事務來實現跨子樹的原子重新命名,這些實現起來都是非常複雜的。目前最新的官方文件仍然不推薦使用多個 MDS(作為備份是可以的)。

GFS

Google 的 GFS 是分散式檔案系統中的先驅和典型代表,由早期的 BigFiles 發展而來。在 2003 年發表的論文中詳細闡述了它的設計理念和細節,對業界影響非常大,後來很多分散式檔案系統都是參照它的設計。

顧名思義,BigFiles/GFS 是為大檔案優化設計的,並不適合平均檔案大小在 1MB 以內的場景。GFS的架構入下圖所示:

image.png

GFS 有一個 Master 節點來管理後設資料(全部載入到記憶體,快照和更新日誌寫到磁碟),檔案劃分成 64MB 的 Chunk 儲存到幾個 ChunkServer 上(直接使用單機檔案系統)。檔案只能追加寫,不用擔心 Chunk 的版本和一致性問題(可以用長度當做版本)。這個使用完全不同的技術來解決後設資料和資料的設計使得系統的複雜度大大簡化,也有足夠的擴充套件能力(如果平均檔案大小大於 256MB,Master 節點每 GB 記憶體可以支撐約 1PB 的資料量)。放棄支援 POSIX 檔案系統的部分功能(比如隨機寫、擴充套件屬性、硬連結等)也進一步簡化了系統複雜度,以換取更好的系統效能、魯棒性和可擴充套件性。

因為 GFS 的成熟穩定,使得 Google 可以更容易地構建上層應用(MapReduce、BigTable等)。後來,Google 開發了擁有更強可擴充套件能力的下一代儲存系統 Colossus,把後設資料和資料儲存徹底分離,實現了後設資料的分散式(自動 Sharding),以及使用Reed Solomon 編碼來降低儲存空間佔用從而降低成本。

HDFS

出自 Yahoo 的 Hadoop 算是 Google 的 GFS、MapReduce 等的開源Java實現版,HDFS 也是基本照搬 GFS 的設計,這裡就不再重複了,下圖是HDFS的架構圖:

image.png

HDFS的可靠性和可擴充套件能力還是非常不錯的,有不少幾千節點和 100PB 級別的部署,支撐大資料應用表現還是很不錯的,少有聽說丟資料的案例(因為沒有配置回收站導致資料被誤刪的除外)。

HDFS 的 HA 方案是後來補上的,做得比較複雜,以至於最早做這個 HA 方案的 Facebook 在很長一段時間(至少 3 年)內都是手動做故障切換(不信任自動故障切換)

因為 NameNode 是 Java 實現的,依賴於預先分配的堆記憶體大小,分配不足容易觸發 Full GC 而影響整個系統的效能。有一些團隊嘗試把它用 C++ 重寫了,但還沒看到有成熟的開源方案。

HDFS 也缺乏成熟的非 Java 客戶端,使得大資料(Hadoop等工具)以外的場景(比如深度學習等)使用起來不太方便。

MooseFS

MooseFS 是來自波蘭的開源分散式 POSIX 檔案系統,也是參照了 GFS 的架構,實現了絕大部分 POSIX 語義和 API,通過一個非常成熟的 FUSE 客戶端掛載後可以像本地檔案系統一樣訪問。MooseFS 的架構如下圖所示:

image.png

MooseFS 支援快照,用它來做資料備份或者備份恢復等還是恢復方便的。

MooseFS 是由 C 實現的,Master 是個非同步事件驅動的單執行緒,類似於 Redis。不過網路部分使用的是 poll 而不是更高效的 epoll,導致併發到 1000 左右時 CPU 消耗非常厲害。

開源的社群版沒有HA,是通過 metalogger 來實現非同步冷備,閉源的收費版有 HA。

為了支援隨機寫操作,MooseFS 中的 chunk 是可以修改的,通過一套版本管理機制來保證資料一致性,這個機制比較複雜容易出現詭異問題(比如叢集重啟後可能會有少數 chunk 實際副本數低於預期)。

JuiceFS

上面說的 GFS、HDFS 和 MooseFS 都是針對自建機房這種軟硬體環境設計的,將資料的可靠性和節點可用性合在一起用多機多副本的方式解決。但是在公有云或者私有云的虛擬機器裡,塊裝置已經是具有三副本可靠性設計的虛擬塊裝置,如果再通過多機多副本的方式來做,會導致資料的成本居高不下(實際上是 9 個拷貝)。

於是我們針對公有云,改進 HDFS 和 MooseFS 的架構,設計了 JuiceFS,架構如下圖所示:

image.png

JuiceFS 使用公有云中已有的物件儲存來替換 DataNode 和 ChunkServer,實現一個完全彈性的 Serverless 的儲存系統。公有云的物件儲存已經很好地解決了大規模資料的安全高效儲存,JuiceFS 只需要專注後設資料的管理,也大大降低了後設資料服務的複雜度(GFS 和 MooseFS 的 master 要同時解決後設資料的儲存和資料塊的健康管理)。我們也對後設資料部分做了很多改進,從一開始就實現了基於 Raft 的高可用。要真正提供一個高可用高效能的服務,後設資料的管理和運維仍然是很有挑戰的,後設資料是以服務的形式提供給使用者。因為 POSIX 檔案系統 API 是應用最最廣泛的 API,我們基於 FUSE 實現了高度 POSIX 相容的客戶端,使用者可以通過一個命令列工具把 JuiceFS 掛載到 Linux 或者 macOS 中,像本地檔案系統一樣快速訪問。

上圖中右邊虛線部分是負責資料儲存和訪問的部分,涉及使用者的資料隱私,它們是完全在客戶自己的賬號和網路環境中,不會跟後設資料服務接觸。我們(Juicedata)沒有任何方法接觸到客戶的內容(後設資料除外,請不要把敏感內容放到檔名裡)。

小結

簡要介紹了下我所瞭解的幾個分散式檔案系統的架構,把他們按照出現的時間順序放在下面的圖裡(箭頭表示後參考了前者或者是新一代版本):

image.png

上圖中上部分藍色的幾個檔案下主要是給大資料場景使用的,實現的是 POSIX 的子集,而下面綠色的幾個是 POSIX 相容的檔案系統。

他們中以 GFS 為代表的後設資料和資料分離的系統設計能夠有效平衡系統的複雜度,有效解決大規模資料的儲存問題(通常也都是大檔案),有更好的可擴充套件性。這個架構下支援後設資料的分散式儲存的 Colossus 和 WarmStorage 更是具有無限的可擴充套件能力。

JuiceFS 作為後來者,學習了 MooseFS 實現分散式 POSIX 檔案系統的方式,也學習了 Facebook 的 WarmStorage 等後設資料和資料徹底分開的思路,希望為公有云或者私有云等場景下提供最好的分散式儲存體驗。JuiceFS 通過將資料儲存到物件儲存的方式,有效避免了使用以上分散式檔案系統時的雙層冗餘(塊儲存的冗餘和分散式系統的多機冗餘)導致的成本過高問題。JuiceFS 還支援所有的公有云,不用擔心某個雲服務鎖定,還能平滑地在公有云或者區之間遷移資料。

最後,如果你手上有公有云賬號,來 JuiceFS 註冊一下,5 分鐘就可以給你的虛擬機器或者自己的 Mac 上掛載一個 PB 級容量的檔案系統了。

推薦閱讀:

如何藉助 JuiceFS 為 AI 模型訓練提速 7 倍

相關文章