天天看點

淺析三款大規模分布式檔案系統架構設計

作者:InfoQ

作者 | 高昌健

策劃 | Tina

當提到檔案系統時,大部分人都很陌生。但實際上我們幾乎每天都會使用它。比如,大家打開 Windows、macOS 或者 Linux,不管是用資料總管還是 Finder,都是在和檔案系統打交道。如果大家曾經手動安裝過作業系統,一定會記得在第一次安裝時需要格式化磁盤,格式化時就需要為磁盤選擇使用哪個檔案系統。

淺析三款大規模分布式檔案系統架構設計

維基百科上的關于檔案系統[1]的定義是:

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+
淺析三款大規模分布式檔案系統架構設計

(圖檔來源:《Modern Operating Systems》10.2.5 小節)

上圖是 Linux 核心的架構,左邊 Virtual file system 區域,也就是虛拟檔案系統簡稱 VFS。它的作用是為了幫助 Linux 去适配不同的檔案系統而設計的,VFS 提供了通用的檔案系統接口,不同的檔案系統實作需要去适配這些接口。

日常使用 Linux 的時候,所有的系統調用請求都會先到達 VFS,然後才會由 VFS 向下請求實際使用的檔案系統。檔案系統的設計者需要遵守 VFS 的接口協定來設計檔案系統,接口是共享的,但是檔案系統具體實作是不同的,每個檔案系統都可以有自己的實作方式。檔案系統再往下是存儲媒體,會根據不同的存儲媒體再去組織存儲的資料形式。

淺析三款大規模分布式檔案系統架構設計

一次寫操作的請求流程

(圖檔來源:《Linux Kernel Development》第 13 章 Filesystem Abstraction Layer)

上圖是一次寫操作的請求流程,在 Linux 裡寫檔案,其實就是一次 write() 系統調用。當你調用 write() 操作請求的時候,它會先到達 VFS,再由 VFS 去調用檔案系統,最後再由檔案系統去把實際的資料寫到本地的存儲媒體。

淺析三款大規模分布式檔案系統架構設計

目錄樹(圖檔來源:《Modern Operating Systems》4.2.2 小節)

上圖是一個目錄樹的結構,在檔案系統裡面,所有資料的組織形式都是這樣一棵樹的結構,從最上面的根節點往下,有不同的目錄和不同的檔案。這顆樹的深度是不确定的,相當于目錄的深度是不确定的,是由每個使用者來決定的,樹的葉子節點就是每一個檔案。

淺析三款大規模分布式檔案系統架構設計

檔案描述符與 inode

(圖檔來源:《Modern Operating Systems》10.6.3 小節)

最右邊的 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

淺析三款大規模分布式檔案系統架構設計

(圖檔來源:The Google File System 論文)

首先還是以提到最多的 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,有興趣的朋友可以閱讀官方部落格[2]。

Tectonic

淺析三款大規模分布式檔案系統架構設計

(圖檔來源:Facebook’s Tectonic Filesystem: Efficiency from Exascale 論文)

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 億的檔案量,這個檔案量對于分布式檔案系統來說,也是一個比較大的規模。在實踐中,百億級基本上可以滿足目前絕大部分的使用場景。

淺析三款大規模分布式檔案系統架構設計

(圖檔來源:Facebook’s Tectonic Filesystem: Efficiency from Exascale 論文)

再來看一下 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]中中繼資料分了 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 開源社群的主力隊員。

引用連結

[1] 檔案系統: https://en.wikipedia.org/wiki/File_system

[2] 官方部落格: https://cloud.google.com/blog/products/storage-data-transfer/a-peek-behind-colossus-googles-file-system

[3] 存儲格式: https://juicefs.com/docs/zh/community/architecture#how-juicefs-store-files

本文轉載來源:

https://www.infoq.cn/article/J3ulcioRIXNfR0HDtZjr

繼續閱讀