什麼是檔案系統
當提到檔案系統,大部分人都很陌生。但我們每個人幾乎每天都會使用到檔案系統,比如大家開啟 Windows、macOS 或者 Linux,不管是用資源管理器還是 Finder,都是在和檔案系統打交道。如果大家有自己動手裝過作業系統的話,第一次安裝的時候一定會有一個步驟就是要格式化磁碟,格式化的時候就需要選擇磁碟需要用哪個檔案系統。
維基百科上的關於檔案系統的定義是:
In computing, file system is a method and data structure that the operating system uses to control how data is stored and retrieved.
簡而言之,檔案系統管理的是某種物理儲存介質(如磁碟、SSD、CD、磁帶等)上的資料。在檔案系統中最基礎的概念就是檔案和目錄,所有的資料都會對應一個檔案,透過目錄以樹形結構來管理和組織這些資料。基於檔案和目錄的組織結構,可以進行一些更高階的配置,比如給檔案配置許可權、統計檔案的大小、修改時間、限制檔案系統的容量上限等。
以下羅列了一些在不同作業系統中比較常見的檔案系統:
- Linux:ext4、XFS、Btrfs
- Windows:NTFS、FAT32
- macOS:APFS、HFS+
上圖是 Linux 核心的架構,左邊 Virtual file system 區域,也就是虛擬檔案系統簡稱 VFS。它的作用是為了幫助 Linux 去適配不同的檔案系統而設計的,VFS 提供了通用的檔案系統介面,不同的檔案系統實現需要去適配這些介面。
日常使用 Linux 的時候,所有的系統呼叫請求都會先到達 VFS,然後才會由 VFS 向下請求實際使用的檔案系統。檔案系統的設計者需要遵守 VFS 的介面協議來設計檔案系統,介面是共享的,但是檔案系統具體實現是不同的,每個檔案系統都可以有自己的實現方式。檔案系統再往下是儲存介質,會根據不同的儲存介質再去組織儲存的資料形式。
上圖是一次寫操作的請求流程,在 Linux 裡寫檔案,其實就是一次 write()
系統呼叫。當你呼叫 write()
操作請求的時候,它會先到達 VFS,再由 VFS 去呼叫檔案系統,最後再由檔案系統去把實際的資料寫到本地的儲存介質。
上圖是一個目錄樹的結構,在檔案系統裡面,所有資料的組織形式都是這樣一棵樹的結構,從最上面的根節點往下,有不同的目錄和不同的檔案。這顆樹的深度是不確定的,相當於目錄的深度是不確定的,是由每個使用者來決定的,樹的葉子節點就是每一個檔案。
最右邊的 inode 就是每個檔案系統內部的資料結構。這個 inode 有可能是一個目錄,也有可能是一個普通的檔案。 Inode 裡面會包含關於檔案的一些元資訊,比如建立時間、建立者、屬於哪個組以及許可權資訊、檔案大小等。此外每個 inode 裡面還會有一些指標或者索引指向實際物理儲存介質上的資料塊。
以上就是實際去訪問一個單機檔案系統時,可能會涉及到的一些資料結構和流程。作為一個引子,讓大家對於檔案系統有一個比較直觀的認識。
分散式檔案系統架構設計
單機的檔案系統已經能夠滿足我們大部分使用場景的需求,管理很多日常需要儲存的資料。但是隨著時代的發展以及資料的爆發增對於資料儲存的需求也是在不斷的增長,分散式檔案系統應運而生。
上面列了一些大家相對比較熟悉或者使用比較多的分散式檔案系統,這裡面有開源的檔案系統,也有公司內部使用的閉源產品。從這張圖可以看到一個非常集中的時間點,2000 年左右有一大批的分散式系統誕生,這些分散式檔案系統至今在我們日常工作中或多或少還是會接觸到。在 2000 年之前也有各種各樣的共享儲存、並行檔案系統、分散式檔案系統,但基本上都是基於一些專用的且比較昂貴的硬體來構建的。
自 2003 年 Google 的 GFS(Google File System)論文公開發表以來,很大程度上影響了後面一大批分散式系統的設計理念和思想。GFS 證明了我們可以用相對廉價的通用計算機,來組建一個足夠強大、可擴充套件、可靠的分散式儲存,完全基於軟體來定義一個檔案系統,而不需要依賴很多專有或者高昂的硬體資源,才能去搭建一套分散式儲存系統。
因此 GFS 很大程度上降低了分佈檔案系統的使用門檻,所以在後續的各個分散式檔案系統上都可以或多或少看到 GFS 的影子。比如雅虎開源的 HDFS 它基本上就是按照 GFS 這篇論文來實現的,HDFS 也是目前大資料領域使用最廣泛的儲存系統。
上圖第四列的「POSIX 相容」表示這個分散式檔案系統對 POSIX 標準的相容性。POSIX(Portable Operating System Interface)是用於規範作業系統實現的一組標準,其中就包含與檔案系統有關的標準。所謂 POSIX 相容,就是滿足這個標準裡面定義的一個檔案系統應該具備的所有特徵,而不是隻具備個別,比如 GFS,它雖然是一個開創性的分散式檔案系統,但其實它並不是 POSIX 相容的檔案系統。
Google 當時在設計 GFS 時做了很多取捨,它捨棄掉了很多傳統單機檔案系統的特性,保留了對於當時 Google 搜尋引擎場景需要的一些分散式儲存的需求。所以嚴格上來說,GFS 並不是一個 POSIX 相容的檔案系統,但是它給了大家一個啟發,還可以這樣設計分散式檔案系統。
接下來我會著重以幾個相對有代表性的分散式檔案系統架構為例,給大家介紹一下,如果要設計一個分散式檔案系統,大概會需要哪些元件以及可能會遇到的一些問題。
GFS
首先還是以提到最多的 GFS 為例,雖然它在 2003 年就公佈了,但它的設計我認為至今也是不過時的,有很多值得借鑑的地方。GFS 的主要元件可以分為三塊,最左邊的 GFS client 也就是它的客戶端,然後就是中間的 GFS master 也就是它的後設資料節點,最下面兩塊是 GFS chunkserver 就是資料實際儲存的節點,master 和 chunkserver 之間是透過網路來通訊,所以說它是一個分散式的檔案系統。Chunkserver 可以隨著資料量的增長不斷地橫向擴充套件。
其中 GFS 最核心的兩塊就是 master 和 chunkserver。我們要實現一個檔案系統,不管是單機還是分散式,都需要去維護檔案目錄、屬性、許可權、連結等資訊,這些資訊是一個檔案系統的後設資料,這些後設資料資訊需要在中心節點 master 裡面去儲存。Master 也包含一個樹狀結構的後設資料設計。
當要儲存實際的應用資料時,最終會落到每一個 chunkserver 節點上,然後 chunkserver 會依賴本地作業系統的檔案系統再去儲存這些檔案。
Chunkserver 和 master、client 之間互相會有連線,比如說 client 端發起一個請求的時候,需要先從 master 獲取到當前檔案的後設資料資訊,再去和 chunkserver 通訊,然後再去獲取實際的資料。在 GFS 裡面所有的檔案都是分塊(chunk)儲存,比如一個 1GB 的大檔案,GFS 會按照一個固定的大小(64MB)對這個檔案進行分塊,分塊了之後會分佈到不同的 chunkserver 上,所以當你讀同一個檔案時其實有可能會涉及到和不同的 chunkserver 通訊。
同時每個檔案的 chunk 會有多個副本來保證資料的可靠性,比如某一個 chunkserver 掛了或者它的磁碟壞了,整個資料的安全性還是有保障的,可以透過副本的機制來幫助你保證資料的可靠性。這是一個很經典的分散式檔案系統設計,現在再去看很多開源的分散式系統實現都或多或少有 GFS 的影子。
這裡不得不提一下,GFS 的下一代產品: Colossus。由於 GFS 的架構設計存在明顯的擴充套件性問題,所以 Google 內部基於 GFS 繼續研發了 Colossus。Colossus 不僅為谷歌內部各種產品提供儲存能力,還作為谷歌雲服務的儲存底座開放給公眾使用。Colossus 在設計上增強了儲存的可擴充套件性,提高了可用性,以處理大規模增長的資料需求。下面即將介紹的 Tectonic 也是對標 Colossus 的儲存系統。篇幅關係,這篇部落格不再展開介紹 Colossus,有興趣的朋友可以閱讀官方部落格。
Tectonic
Tectonic 是 Meta(Facebook)內部目前最大的一個分散式檔案系統。Tectonic 專案大概在 2014 年就開始做了(之前被叫做 Warm Storage),但直到 2021 年才公開發表論文來介紹整個分散式檔案系統的架構設計。
在研發 Tectonic 之前,Meta 公司內部主要使用 HDFS、Haystack 和 f4 來儲存資料,HDFS 用在數倉場景(受限於單叢集的儲存容量,部署了數十個叢集),Haystack 和 f4 用在非結構化資料儲存場景。Tectonic 的定位即是在一個叢集裡滿足這 3 種儲存支撐的業務場景需求。和 GFS 一樣,Tectonic 也主要由三部分構成,分別是 Client Library、Metadata Store 和 Chunk Store。
Tectonic 比較創新的點在於它在 Metadata 這一層做了分層處理,以及存算分離的架構設計 。從架構圖可以看到 Metadata 分了三層:Name layer、File layer 和 Block layer。傳統分散式檔案系統會把所有的後設資料都看作同一類資料,不會把它們顯式區分。在 Tectonic 的設計中,Name layer 是與檔案的名字或者目錄結構有關的後設資料,File layer 是跟當前檔案本身的一些屬性相關的資料,Block layer 是每一個資料塊在 Chunk Store 位置的後設資料。
Tectonic 之所以要做這樣一個分層的設計是因為它是一個非常大規模的分散式檔案系統,特別是在 Meta 這樣的量級下(EB 級資料)。在這種規模下,對於 Metadata Store 的負載能力以及擴充套件性有著非常高的要求。
第二點創新在於後設資料的存算分離設計,前面提到這三個 layer 其實是無狀態的,可以根據業務負載去橫向擴充套件。但是上圖中的 Key-value Store 是一個有狀態的儲存,layer 和 Key-value Store 之間透過網路通訊。
Key-value Store 並不完全是 Tectonic 自己研發的,而是用了 Meta 內部一個叫做 ZippyDB 的分散式 KV 儲存來支援後設資料的儲存。ZippyDB 是基於 RocksDB 以及 Paxos 共識演算法來實現的一個分散式 KV 儲存。Tectonic 依賴 ZippyDB 的 KV 儲存以及它提供的事務來保證整個檔案系統元資訊的一致性和原子性。
這裡的事務功能是非常重要的一點,如果要實現一個大規模的分散式檔案系統,勢必要把 Metadata Store 做橫向擴充套件。橫向擴充套件之後就涉及資料分片,但是在檔案系統裡面有一個非常重要的語義是強一致性,比如重新命名一個目錄,目錄裡面會涉及到很多的子目錄,這個時候要怎麼去高效地重新命名目錄以及保證重新命名過程中的一致性,是分散式檔案系統設計中是一個非常重要的點,也是業界普遍認為的難點。
Tectonic 的實現方案就是依賴底層的 ZippyDB 的事務特性來保證當僅涉及單個分片的後設資料時,檔案系統操作一定是事務性以及強一致性的。但由於 ZippyDB 不支援跨分片的事務,因此在處理跨目錄的後設資料請求(比如將檔案從一個目錄移動到另一個目錄)時 Tectonic 無法保證原子性。
在 Chunk Store 層 Tectonic 也有創新,上文提到 GFS 是透過多副本的方式來保證資料的可靠性和安全性。多副本最大的弊端在於它的儲存成本,比如說你可能只存了1TB 的資料,但是傳統來說會保留三個副本,那麼至少需要 3TB 的空間來儲存,這樣使得儲存成本成倍增長。對於小數量級的檔案系統可能還好,但是對於像 Meta 這種 EB 級的檔案系統,三副本的設計機制會帶來非常高昂的成本,所以他們在 Chunk Store 層使用 EC(Erasure Code)也就是糾刪碼的方式去實現。透過這種方式可以只用大概 1.2~1.5 倍的冗餘空間,就能夠保證整個叢集資料的可靠性和安全性,相比三副本的冗餘機制節省了很大的儲存成本。Tectonic 的 EC 設計細到可以針對每一個 chunk 進行配置,是非常靈活的。
同時 Tectonic 也支援多副本的方式,取決於上層業務需要什麼樣的儲存形式。EC 不需要特別大的的空間就可以保證整體資料的可靠性,但是 EC 的缺點在於當資料損壞或丟失時重建資料的成本很高,需要額外消耗更多計算和 IO 資源。
透過論文我們得知目前 Meta 最大的 Tectonic 叢集大概有四千臺儲存節點,總的容量大概有 1590PB,有 100 億的檔案量,這個檔案量對於分散式檔案系統來說,也是一個比較大的規模。在實踐中,百億級基本上可以滿足目前絕大部分的使用場景。
再來看一下 Tectonic 中 layer 的設計,Name、File、Block 這三個 layer 實際對應到底層的 KV 儲存裡的資料結構如上圖所示。比如說 Name layer 這一層是以目錄 ID 作為 key 進行分片,File layer 是透過檔案 ID 進行分片,Block layer 是透過塊 ID 進行分片。
Tectonic 把分散式檔案系統的後設資料抽象成了一個簡單的 KV 模型,這樣可以非常好的去做橫向擴充套件以及負載均衡,可以有效防止資料訪問的熱點問題。
JuiceFS
JuiceFS 誕生於 2017 年,比 GFS 和 Tectonic 都要晚,相比前兩個系統的誕生年代,外部環境已經發生了翻天覆地的變化。
首先硬體資源已經有了突飛猛進的發展,作為對比,當年 Google 機房的網路頻寬只有 100Mbps(資料來源:The Google File System 論文),而現在 AWS 上機器的網路頻寬已經能達到 100Gbps,是當年的 1000 倍!
其次雲端計算已經進入了主流市場,不管是公有云、私有云還是混合雲,企業都已經邁入了「雲時代」。而云時代為企業的基礎設施架構帶來了全新挑戰,傳統基於 IDC 環境設計的基礎設施一旦想要上雲,可能都會面臨種種問題。如何最大程度上發揮雲端計算的優勢是基礎設施更好融入雲環境的必要條件,固守陳規只會事倍功半。
同時,GFS 和 Tectonic 都是僅服務公司內部業務的系統,雖然規模很大,但需求相對單一。而 JuiceFS 定位於服務廣大外部使用者、滿足多樣化場景的需求,因而在架構設計上與這兩個檔案系統也大有不同。
基於這些變化和差異,我們再來看看 JuiceFS 的架構。同樣的,JuiceFS 也是由 3 部分組成:後設資料引擎、資料儲存和客戶端。雖然大體框架上類似,但其實每一部分的設計 JuiceFS 都有著一些不太一樣的地方。
首先是資料儲存這部分,相比 GFS 和 Tectonic 使用自研的資料儲存服務,JuiceFS 在架構設計上順應了雲原生時代的特點,直接使用物件儲存作為資料儲存。前面看到 Tectonic 為了儲存 EB 級的資料用了 4000 多臺伺服器,可想而知,如此大規模儲存叢集的運維成本也必然不小。對於普通使用者來說,物件儲存的好處是開箱即用、容量彈性,運維複雜度陡然下降。物件儲存也支援 Tectonic 中使用的 EC 特性,因此儲存成本相比一些多副本的分散式檔案系統也能降低不少。
但是物件儲存的缺點也很明顯,例如不支援修改物件、後設資料效能差、無法保證強一致性、隨機讀效能差等。這些問題都被 JuiceFS 設計的獨立後設資料引擎,Chunk、Slice、Block 三層資料架構設計,以及多級快取解決了。
其次是後設資料引擎,JuiceFS 可使用一些開源資料庫作為後設資料的底層儲存。這一點和 Tectonic 很像,但 JuiceFS 更進了一步,不僅支援分散式 KV,還支援 Redis、關係型資料庫等儲存引擎,讓使用者可以靈活地根據自己的使用場景選擇最適合的方案,這是基於 JuiceFS 定位為一款通用型檔案系統所做出的架構設計。使用開源資料庫的另一個好處是這些資料庫在公有云上通常都有全託管服務,因此對於使用者來說運維成本幾乎為零。
前面提到 Tectonic 為了保證後設資料的強一致性選擇了 ZippyDB 這個支援事務的 KV 儲存,但 Tectonic 也只能保證單分片後設資料操作的事務性,而 JuiceFS 對於事務性有著更嚴格的要求,需要保證全域性強一致性(即要求跨分片的事務性)。因此目前支援的所有資料庫都必須具有單機或者分散式事務特性,否則是沒有辦法作為後設資料引擎接入進來的(一個例子就是 Redis Cluster 不支援跨 slot 的事務)。基於可以橫向擴充套件的後設資料引擎(比如 TiKV),JuiceFS 目前已經能做到在單個檔案系統中儲存 200 多億個檔案,滿足企業海量資料的儲存需求。
上圖是使用 KV 儲存(比如 TiKV)作為 JuiceFS 後設資料引擎時的資料結構設計,如果對比 Tectonic 的設計,既有相似之處也有一些大的差異。比如第一個 key,在 JuiceFS 的設計裡沒有對檔案和目錄進行區分,同時檔案或目錄的屬性資訊也沒有放在 value 裡,而是有一個單獨的 key 用於儲存屬性資訊(即第三個 key)。
第二個 key 用於儲存資料對應的塊 ID,由於 JuiceFS 基於物件儲存,因此不需要像 Tectonic 那樣儲存具體的磁碟資訊,只需要透過某種方式得到物件的 key 即可。在 JuiceFS 的儲存格式中後設資料分了 3 層:Chunk、Slice、Block,其中 Chunk 是固定的 64MiB 大小,所以第二個 key 中的 chunk_index
是可以透過檔案大小、offset 以及 64MiB 直接計算得出。透過這個 key 獲取到的 value 是一組 Slice 資訊,其中包含 Slice 的 ID、長度等,結合這些資訊就可以算出物件儲存上的 key,最終實現讀取或者寫入資料。
最後有一點需要特別注意,為了減少執行分散式事務帶來的開銷,第三個 key 在設計上需要靠近前面兩個 key,確保事務儘量在單個後設資料引擎節點上完成。不過如果分散式事務無法避免,JuiceFS 底層的後設資料引擎也支援(效能略有下降),確保後設資料操作的原子性。
最後來看看客戶端的設計。JuiceFS 和另外兩個系統最大的區別就是這是一個同時支援多種標準訪問方式的客戶端,包括 POSIX、HDFS、S3、Kubernetes CSI 等。GFS 的客戶端基本可以認為是一個非標準協議的客戶端,不支援 POSIX 標準,只支援追加寫,因此只能用在單一場景。Tectonic 的客戶端和 GFS 差不多,也不支援 POSIX 標準,只支援追加寫,但 Tectonic 採用了一種富客戶端的設計,把很多功能都放在客戶端這一邊來實現,這樣也使得客戶端有著最大的靈活性。此外 JuiceFS 的客戶端還提供了快取加速特性,這對於雲原生架構下的儲存分離場景是非常有價值的。
結語
檔案系統誕生於上個世紀 60 年代,隨著時代的發展,檔案系統也在不斷演進。一方面由於網際網路的普及,資料規模爆發式增長,檔案系統經歷了從單機到分散式的架構升級,Google 和 Meta 這樣的公司便是其中的引領者。
另一方面,雲端計算的誕生和流行推動著雲上儲存的發展,企業用雲進行備份和存檔已逐漸成為主流,一些在本地機房進行的高效能運算、大資料場景,也已經開始向雲端遷移,這些對效能要求更高的場景給檔案儲存提出了新的挑戰。JuiceFS 誕生於這樣的時代背景,作為一款基於物件儲存的分散式檔案系統,JuiceFS 希望能夠為更多不同規模的公司和更多樣化的場景提供可擴充套件的檔案儲存方案。
如有幫助的話歡迎關注我們專案 Juicedata/JuiceFS 喲! (0ᴗ0✿)