什么是文件系統(tǒng)纫塌?
文件系統(tǒng)是計算機(jī)中一個非常重要的組件桶良,為存儲設(shè)備提供一致的訪問和管理方式嗜侮。在不同的操作系統(tǒng)中焊虏,文件系統(tǒng)會有一些差別淡喜,但也有一些共性幾十年都沒怎么變化:
數(shù)據(jù)是以文件的形式存在,提供 Open诵闭、Read炼团、Write、Seek疏尿、Close 等API 進(jìn)行訪問瘟芝;
文件以樹形目錄進(jìn)行組織,提供原子的重命名(Rename)操作改變文件或者目錄的位置褥琐。
文件系統(tǒng)提供的訪問和管理方法支撐了絕大部分的計算機(jī)應(yīng)用锌俱,Unix 的“萬物皆文件”的理念更是凸顯了它的重要地位。文件系統(tǒng)的復(fù)雜性使得它的可擴(kuò)展性未能跟得上互聯(lián)網(wǎng)的高速發(fā)展敌呈,極大簡化了的對象存儲及時填補了空缺得以快速發(fā)展起來贸宏。因為對象存儲缺乏樹狀結(jié)構(gòu)也不支持原子重命名操作,跟文件系統(tǒng)有很大的差別磕洪,本文暫不討論吭练。
單機(jī)文件系統(tǒng)的挑戰(zhàn)
絕大多數(shù)文件系統(tǒng)都是單機(jī)的,在單機(jī)操作系統(tǒng)內(nèi)為一個或者多個存儲設(shè)備提供訪問和管理析显。隨著互聯(lián)網(wǎng)的高速發(fā)展鲫咽,單機(jī)文件系統(tǒng)面臨很多的挑戰(zhàn):
共享:無法同時為分布在多個機(jī)器中的應(yīng)用提供訪問,于是有了 NFS 協(xié)議,可以將單機(jī)文件系統(tǒng)通過網(wǎng)絡(luò)的方式同時提供給多個機(jī)器訪問分尸。
容量:無法提供足夠空間來存儲數(shù)據(jù)姊舵,數(shù)據(jù)只好分散在多個隔離的單機(jī)文件系統(tǒng)里。
性能:無法滿足某些應(yīng)用需要非常高的讀寫性能要求寓落,應(yīng)用只好做邏輯拆分同時讀寫多個文件系統(tǒng)。
可靠性:受限于單個機(jī)器的可靠性荞下,機(jī)器故障可能導(dǎo)致數(shù)據(jù)丟失伶选。
可用性:受限于單個操作系統(tǒng)的可用性,故障或者重啟等運維操作會導(dǎo)致不可用尖昏。
隨著互聯(lián)網(wǎng)的高速發(fā)展仰税,這些問題變得日益突出,涌現(xiàn)出了一些分布式文件系統(tǒng)來應(yīng)對這些挑戰(zhàn)抽诉。
下面介紹幾個我了解過的分布式文件系統(tǒng)的基本架構(gòu)陨簇,并比較不同架構(gòu)的優(yōu)點和局限。
GlusterFS
GlusterFS 是由美國的 Gluster 公司開發(fā)的 POSIX 分布式文件系統(tǒng)(以 GPL 開源)迹淌,2007年發(fā)布第一個公開版本河绽,2011年被 Redhat 收購。
它的基本思路就是通過一個無狀態(tài)的中間件把多個單機(jī)文件系統(tǒng)融合成統(tǒng)一的名字空間(namespace)提供給用戶唉窃。這個中間件是由一系列可疊加的轉(zhuǎn)換器(Translator)實現(xiàn)耙饰,每個轉(zhuǎn)換器解決一個問題,比如數(shù)據(jù)分布纹份、復(fù)制苟跪、拆分、緩存蔓涧、鎖等等件已,用戶可以根據(jù)具體的應(yīng)用場景需要靈活配置。比如一個典型的分布式卷如下圖所示:
Server1 和 Server2 構(gòu)成有 2 副本的 Volume0元暴,Server3 和 Server4 構(gòu)成 Volume1篷扩,它們再融合成有更大空間的分布式卷。
優(yōu)點:
數(shù)據(jù)文件最終以相同的目錄結(jié)構(gòu)保存在單機(jī)文件系統(tǒng)上昨寞,不用擔(dān)心 GlusterFS 的不可用導(dǎo)致數(shù)據(jù)丟失瞻惋。
沒有明顯的單點問題,可線性擴(kuò)展援岩。
對大量小文件的支持估計還不錯歼狼。
挑戰(zhàn):
這種結(jié)構(gòu)是相對靜態(tài)的,不容易調(diào)整享怀,也要求各個存儲節(jié)點有相同的配置羽峰,當(dāng)數(shù)據(jù)或者訪問不均衡時沒法進(jìn)行空間或者負(fù)載調(diào)整。故障恢復(fù)能力也比較弱,比如 Server1 故障時梅屉,Server2 上的文件就沒辦法在健康的 3 或者 4上增加拷貝保障數(shù)據(jù)可靠值纱。
因為缺乏獨立的元數(shù)據(jù)服務(wù),要求所有存儲節(jié)點都會有完整的數(shù)據(jù)目錄結(jié)構(gòu)坯汤,遍歷目錄或者做目錄結(jié)構(gòu)調(diào)整時需要訪問所有節(jié)點才能得到正確結(jié)果虐唠,導(dǎo)致整個系統(tǒng)的可擴(kuò)展能力有限,擴(kuò)展到幾十個節(jié)點時還行惰聂,很難有效地管理上百個節(jié)點疆偿。
CephFS
CephFS 始于 Sage Weil 的博士論文研究,目標(biāo)是實現(xiàn)分布式的元數(shù)據(jù)管理以支持 EB 級別數(shù)據(jù)規(guī)模搓幌。2012年杆故,Sage Weil 成立了 InkTank 繼續(xù)支持 CephFS 的開發(fā),于 2014年被 Redhat 收購溉愁。直到 2016 年处铛,CephFS 才發(fā)布可用于生產(chǎn)環(huán)境的穩(wěn)定版(CephFS 的元數(shù)據(jù)部分仍然是單機(jī)的)。現(xiàn)在拐揭,CephFS 的分布式元數(shù)據(jù)仍然不成熟撤蟆。
Ceph 是一個分層的架構(gòu),底層是一個基于 CRUSH(哈希)的分布式對象存儲投队,上層提供對象存儲(RADOSGW)枫疆、塊存儲(RDB)和文件系統(tǒng)(CephFS)三個API,如下圖所示:
用一套存儲系統(tǒng)來滿足多個不同場景的存儲需求(虛擬機(jī)鏡像敷鸦、海量小文件和通用文件存儲)還是非常吸引人的扒披,但因為系統(tǒng)的復(fù)雜性需要很強的運維能力才能支撐碟案,實際上目前只有塊存儲還是比較成熟應(yīng)用得比較多价说,對象存儲和文件系統(tǒng)都不太理想鳖目,聽到一些使用案例用過一段時間后就放棄了领迈。
CephFS 的架構(gòu)如下圖所示:
CephFS 是由 MDS(Metadata Daemon) 實現(xiàn)的,它是一個或者多個無狀態(tài)的元數(shù)據(jù)服務(wù)衷蜓,從底層的 OSD 加載文件系統(tǒng)的元信息累提,并緩存到內(nèi)存中以提高訪問速度。因為 MDS 是無狀態(tài)的磁浇,可以配置多個備用節(jié)點來實現(xiàn) HA斋陪,相對比較容易。不過備份節(jié)點沒有緩存置吓,需要重新預(yù)熱鳍贾,有可能故障恢復(fù)時間會比較長。
因為從存儲層加載或者寫入數(shù)據(jù)會比較慢交洗,MDS 必須使用多線程來提高吞吐量,各種并發(fā)的文件系統(tǒng)操作導(dǎo)致復(fù)雜度大大上升橡淑,容易發(fā)生死鎖,或者因為 IO 比較慢導(dǎo)致的性能大幅下降置森。為了獲得比較好的性能符糊,MDS 往往需要有足夠多的內(nèi)存來緩存大部分元數(shù)據(jù),這也限制了它實際的支撐能力男娄。
當(dāng)有多個活躍的 MDS 時行贪,目錄結(jié)構(gòu)中的一部分(子樹)可以動態(tài)的分配到某個MDS并完全由它來處理相關(guān)請求,以達(dá)到水平擴(kuò)展的目的模闲。多個活躍之前,不可避免地需要各自鎖機(jī)制來協(xié)商對子樹的所有權(quán)橄浓,以及通過分布式事務(wù)來實現(xiàn)跨子樹的原子重命名泪勒,這些實現(xiàn)起來都是非常復(fù)雜的叼旋。目前最新的官方文檔仍然不推薦使用多個 MDS(作為備份是可以的)。
GFS
Google 的 GFS 是分布式文件系統(tǒng)中的先驅(qū)和典型代表,由早期的 BigFiles 發(fā)展而來。在 2003 年發(fā)表的論文中詳細(xì)闡述了它的設(shè)計理念和細(xì)節(jié)饿凛,對業(yè)界影響非常大纠吴,后來很多分布式文件系統(tǒng)都是參照它的設(shè)計锅减。
顧名思義休玩,BigFiles/GFS 是為大文件優(yōu)化設(shè)計的,并不適合平均文件大小在 1MB 以內(nèi)的場景劫狠。GFS的架構(gòu)入下圖所示:
GFS 有一個 Master 節(jié)點來管理元數(shù)據(jù)(全部加載到內(nèi)存拴疤,快照和更新日志寫到磁盤),文件劃分成 64MB 的 Chunk 存儲到幾個 ChunkServer 上(直接使用單機(jī)文件系統(tǒng))独泞。文件只能追加寫呐矾,不用擔(dān)心 Chunk 的版本和一致性問題(可以用長度當(dāng)做版本)。這個使用完全不同的技術(shù)來解決元數(shù)據(jù)和數(shù)據(jù)的設(shè)計使得系統(tǒng)的復(fù)雜度大大簡化懦砂,也有足夠的擴(kuò)展能力(如果平均文件大小大于 256MB蜒犯,Master 節(jié)點每 GB 內(nèi)存可以支撐約 1PB 的數(shù)據(jù)量)组橄。放棄支持 POSIX 文件系統(tǒng)的部分功能(比如隨機(jī)寫、擴(kuò)展屬性罚随、硬鏈接等)也進(jìn)一步簡化了系統(tǒng)復(fù)雜度玉工,以換取更好的系統(tǒng)性能、魯棒性和可擴(kuò)展性淘菩。
因為 GFS 的成熟穩(wěn)定遵班,使得 Google 可以更容易地構(gòu)建上層應(yīng)用(MapReduce、BigTable等)潮改。后來狭郑,Google 開發(fā)了擁有更強可擴(kuò)展能力的下一代存儲系統(tǒng) Colossus,把元數(shù)據(jù)和數(shù)據(jù)存儲徹底分離汇在,實現(xiàn)了元數(shù)據(jù)的分布式(自動 Sharding)翰萨,以及使用Reed Solomon 編碼來降低存儲空間占用從而降低成本。
HDFS
出自 Yahoo 的 Hadoop 算是 Google 的 GFS糕殉、MapReduce 等的開源Java實現(xiàn)版缨历,HDFS 也是基本照搬 GFS 的設(shè)計,這里就不再重復(fù)了糙麦,下圖是HDFS的架構(gòu)圖:
HDFS的可靠性和可擴(kuò)展能力還是非常不錯的,有不少幾千節(jié)點和 100PB 級別的部署丛肮,支撐大數(shù)據(jù)應(yīng)用表現(xiàn)還是很不錯的赡磅,少有聽說丟數(shù)據(jù)的案例(因為沒有配置回收站導(dǎo)致數(shù)據(jù)被誤刪的除外)。
HDFS 的 HA 方案是后來補上的宝与,做得比較復(fù)雜焚廊,以至于最早做這個 HA 方案的 Facebook 在很長一段時間(至少 3 年)內(nèi)都是手動做故障切換(不信任自動故障切換)。
因為 NameNode 是 Java 實現(xiàn)的习劫,依賴于預(yù)先分配的堆內(nèi)存大小咆瘟,分配不足容易觸發(fā) Full GC 而影響整個系統(tǒng)的性能。有一些團(tuán)隊嘗試把它用 C++ 重寫了诽里,但還沒看到有成熟的開源方案袒餐。
HDFS 也缺乏成熟的非 Java 客戶端,使得大數(shù)據(jù)(Hadoop等工具)以外的場景(比如深度學(xué)習(xí)等)使用起來不太方便谤狡。
MooseFS
MooseFS 是來自波蘭的開源分布式 POSIX 文件系統(tǒng)灸眼,也是參照了 GFS 的架構(gòu),實現(xiàn)了絕大部分 POSIX 語義和 API墓懂,通過一個非常成熟的 FUSE 客戶端掛載后可以像本地文件系統(tǒng)一樣訪問焰宣。MooseFS 的架構(gòu)如下圖所示:
MooseFS 支持快照,用它來做數(shù)據(jù)備份或者備份恢復(fù)等還是恢復(fù)方便的捕仔。
MooseFS 是由 C 實現(xiàn)的匕积,Master 是個異步事件驅(qū)動的單線程盈罐,類似于 Redis。不過網(wǎng)絡(luò)部分使用的是 poll 而不是更高效的 epoll闪唆,導(dǎo)致并發(fā)到 1000 左右時 CPU 消耗非常厲害盅粪。
開源的社區(qū)版沒有HA,是通過 metalogger 來實現(xiàn)異步冷備苞氮,閉源的收費版有 HA湾揽。
為了支持隨機(jī)寫操作,MooseFS 中的 chunk 是可以修改的笼吟,通過一套版本管理機(jī)制來保證數(shù)據(jù)一致性库物,這個機(jī)制比較復(fù)雜容易出現(xiàn)詭異問題(比如集群重啟后可能會有少數(shù) chunk 實際副本數(shù)低于預(yù)期)。
JuiceFS
上面說的 GFS贷帮、HDFS 和 MooseFS 都是針對自建機(jī)房這種軟硬件環(huán)境設(shè)計的戚揭,將數(shù)據(jù)的可靠性和節(jié)點可用性合在一起用多機(jī)多副本的方式解決。但是在公有云或者私有云的虛擬機(jī)里撵枢,塊設(shè)備已經(jīng)是具有三副本可靠性設(shè)計的虛擬塊設(shè)備民晒,如果再通過多機(jī)多副本的方式來做,會導(dǎo)致數(shù)據(jù)的成本居高不下(實際上是 9 個拷貝)锄禽。
于是我們針對公有云潜必,改進(jìn) HDFS 和 MooseFS 的架構(gòu),設(shè)計了 JuiceFS沃但,架構(gòu)如下圖所示:
JuiceFS 使用公有云中已有的對象存儲來替換 DataNode 和 ChunkServer磁滚,實現(xiàn)一個完全彈性的 Serverless 的存儲系統(tǒng)。公有云的對象存儲已經(jīng)很好地解決了大規(guī)模數(shù)據(jù)的安全高效存儲宵晚,JuiceFS 只需要專注元數(shù)據(jù)的管理垂攘,也大大降低了元數(shù)據(jù)服務(wù)的復(fù)雜度(GFS 和 MooseFS 的 master 要同時解決元數(shù)據(jù)的存儲和數(shù)據(jù)塊的健康管理)。我們也對元數(shù)據(jù)部分做了很多改進(jìn)淤刃,從一開始就實現(xiàn)了基于 Raft 的高可用晒他。要真正提供一個高可用高性能的服務(wù),元數(shù)據(jù)的管理和運維仍然是很有挑戰(zhàn)的逸贾,元數(shù)據(jù)是以服務(wù)的形式提供給用戶陨仅。因為 POSIX 文件系統(tǒng) API 是應(yīng)用最最廣泛的 API,我們基于 FUSE 實現(xiàn)了高度 POSIX 兼容的客戶端铝侵,用戶可以通過一個命令行工具把 JuiceFS 掛載到 Linux 或者 macOS 中掂名,像本地文件系統(tǒng)一樣快速訪問。
上圖中右邊虛線部分是負(fù)責(zé)數(shù)據(jù)存儲和訪問的部分哟沫,涉及用戶的數(shù)據(jù)隱私饺蔑,它們是完全在客戶自己的賬號和網(wǎng)絡(luò)環(huán)境中,不會跟元數(shù)據(jù)服務(wù)接觸嗜诀。我們(Juicedata)沒有任何方法接觸到客戶的內(nèi)容(元數(shù)據(jù)除外猾警,請不要把敏感內(nèi)容放到文件名里)孔祸。
小結(jié)
簡要介紹了下我所了解的幾個分布式文件系統(tǒng)的架構(gòu),把他們按照出現(xiàn)的時間順序放在下面的圖里(箭頭表示后參考了前者或者是新一代版本):
上圖中上部分藍(lán)色的幾個文件下主要是給大數(shù)據(jù)場景使用的发皿,實現(xiàn)的是 POSIX 的子集崔慧,而下面綠色的幾個是 POSIX 兼容的文件系統(tǒng)。
他們中以 GFS 為代表的元數(shù)據(jù)和數(shù)據(jù)分離的系統(tǒng)設(shè)計能夠有效平衡系統(tǒng)的復(fù)雜度穴墅,有效解決大規(guī)模數(shù)據(jù)的存儲問題(通常也都是大文件)惶室,有更好的可擴(kuò)展性。這個架構(gòu)下支持元數(shù)據(jù)的分布式存儲的 Colossus 和 WarmStorage 更是具有無限的可擴(kuò)展能力玄货。
JuiceFS 作為后來者皇钞,學(xué)習(xí)了 MooseFS 實現(xiàn)分布式 POSIX 文件系統(tǒng)的方式,也學(xué)習(xí)了 Facebook 的 WarmStorage 等元數(shù)據(jù)和數(shù)據(jù)徹底分開的思路松捉,希望為公有云或者私有云等場景下提供最好的分布式存儲體驗夹界。JuiceFS 通過將數(shù)據(jù)存儲到對象存儲的方式,有效避免了使用以上分布式文件系統(tǒng)時的雙層冗余(塊存儲的冗余和分布式系統(tǒng)的多機(jī)冗余)導(dǎo)致的成本過高問題隘世。JuiceFS 還支持所有的公有云可柿,不用擔(dān)心某個云服務(wù)鎖定,還能平滑地在公有云或者區(qū)之間遷移數(shù)據(jù)丙者。
最后复斥,如果你手上有公有云賬號,來 JuiceFS 注冊一下械媒,5 分鐘就可以給你的虛擬機(jī)或者自己的 Mac 上掛載一個 PB 級容量的文件系統(tǒng)了目锭。
推薦閱讀: