開源分佈式文件系統大檢閱

前言

我們的YRCloudFile是一款面向雲時代的分佈式文件系統,它的主要特點是支持海量小文件的高性能數據訪問,對Kubernetes平臺的無縫支持,混合雲場景下的數據支撐。我們在開發YRCloudFile時,也會去了解業界主流的分佈式文件系統,學習其優點,避免其缺點。本文討論幾個我們曾調查過的主流的分佈式文件系統,它們都是開源系統,因爲這樣能收集到豐富的資料,能看到代碼,使得了解及討論更爲清晰。

我們在調研一個分佈式文件系統時,主要關注其核心架構,包括以下幾個方面:

1)它的元數據方案,比如是否有元數據集羣,元數據如何組織、元數據的放置策略等。

2)元數據的副本機制及一致性,是EC還是多副本,副本間是同步寫還是異步寫,數據一致性如何。

3)數據的副本機制及一致性,即是EC還是多副本,以及副本間數據一致性問題。

圍繞這幾個核心問題,我們會做一些擴展分析,比如系統的可用性、系統的性能等。

本文要討論的分佈式文件系統,以及選取它們進行分析和了解基於以下一些考慮:

1) HDFS: 選取理由是經典,場景主要用於大數據分析,資料豐富,用戶數量大。

2) MooseFS:簡單、但非常典型的設計,LizardFS是其變種。

3) Lustre:廣爲人知,被衆人當做比較的對象,背後有商業公司,但代碼是開放可下載的。

4) GlusterFS: 老牌分佈式文件系統,應用衆多,國內很早開始就有人投入GlusterFS二次研發,其一致性hash的思路也頗爲經典。

5) CephFS: 近年來最火的分佈式存儲Ceph,沒有之一,個人認爲是在分佈式存儲理論和實踐上的集大成者。

HDFS

全稱爲The Hadoop Distributed File System,適用於Hadoop大數據生態,主要存儲大文件,並定義文件模式是write-once-read-many,來極大簡化數據一致性方面的問題。

引用官網其架構圖爲:

 

HDFS剛開始是單Namenode(可以理解爲HDFS的元數據節點),這成爲容量和性能的瓶頸點。後來再去做了多Namenode。

HDFS並不是一個通用型的分佈式文件系統,即並不提供完整的POSIX語義,至少它的設計目標就絕不是,它發展到後來也不能勝任爲通用性文件系統。它特點明顯,積年來資料很多,本文也就不過多贅述。

MooseFS 

如果你是一個文件系統的狂熱愛好者和開發者,計劃短期內寫一個分佈式文件系統,你可能會這麼做:

1) 元數據部分

使用獨立的元數據服務,爲了簡單化,並不做成元數據集羣,而做成單元數據服務器,就像HDFS Namenode那樣。

爲了避免這個單點元數據服務離線、數據損毀帶來的集羣不可用以及數據丟失,你會部署另一個或多個元數據服務作爲backup,形成一主多從架構。但主從之間如何同步數據,可能是實時同步,也可能是異步同步。

另外,關於爲了簡單化,元數據服務的存儲直接基於本地文件系統,如ext4。

2) 數據部分

爲了簡單化,數據服務存儲也是基於本地文件系統。爲了容錯,跨服務器存儲多個數據副本。

這麼做的明顯缺點是單元數據服務是瓶頸,既限制了集羣支持的最大文件數目,也限制了集羣併發訪問的性能。

MooseFS正好是這個架構,如官方示意圖所示,它將元數據服務稱之爲Master Server,將數據服務稱之爲Chunk Server。

我們通過分析MooseFS的讀寫流程,來分析它在數據一致性方面是否有問題。這裏我們參考了"MooseFS 3.0 User’s Manual" (https://moosefs.com/Content/Downloads/moosefs-3-0-users-manual.pdf)。

讀流程示意圖,需特別注意的是MooseFS所有副本都能提供讀:

寫流程示意圖:

從寫流程能看出,MooseFS使用的是chain replication方式,這個方式本身沒有問題。不過從公開資料看,並未找到MooseFS多副本寫有事務處理,且它的任意副本都支持讀取,故而猜測MooseFS在故障情況下是存在數據一致性問題的。

git clone https://github.com/moosefs/moosefs.git
git checkout v3.0.111

拿最新的代碼,根據keyword CLTOCS_WRITE_DATA,可以看到寫數據的代碼流程。會發現兩個問題:

1)多副本寫,針對故障時副本一致性問題,並未有什麼機制來確保一致。

2)本地數據寫入調用hdd_write(),它在內部調用pwrite(),數據並未實時落盤,而是落在pagecache,再由pagecache下刷機制去負責落盤。

可以構造一個場景,client寫入數據ABC,副本1寫入了AB,副本2寫入了A,此時集羣掉電。在集羣重啓後,集羣中存在不一致的數據。

構造另一個場景,client寫入數據ABC,副本1和副本2都寫入成功,但並未下刷,且MooseFS反饋給client說寫入成功。此時集羣掉電並重啓後,副本1和副本2可能不一致,client讀取的數據跟被承諾的可能不同。

實際上我們在之前工作中,維護過一套線上MooseFS系統,我們當時分析出MooseFS這一問題。今天寫這個文章時,我們重新拿了MooseFS最新的代碼,閱讀了針對性部分,發現這個數據一致性問題如故。

https://moosefs.com/

Lustre

Lustre在HPC領域應用很廣,一定有其特別之處。不過我們仍是主要關注其元數據和數據架構,以及數據一致性方面的問題。

Lustre架構跟MooseFS類似,都是典型的有元數據服務的架構。不過Lustre似乎並未提供副本機制(兩副本機制需主動觸發,非同步副本),也許是它面對的HPC場景,並且數據空間來源於後端的SAN陣列,所以它不需要提供數據冗餘。

數據冗餘依賴後端SAN陣列保障,數據一致性問題就被天然繞開了。我們因此也暫時不去深入瞭解。

http://lustre.org/

GlusterFS

GlusterFS是非常知名的一個分佈式文件系統,國內不少公司很早就在做GlusterFS的二次開發,關於GlusterFS最適合的應用場景,大家討論的最多的是視頻存儲和日誌存儲,其IO特點是大塊數據順序讀寫,這很好理解,一般文件系統都能勝任這一場景。

另一方面,提及GlusterFS,大家討論最多的概念是“一致性哈希”,“無中心架構”,“堆棧式設計”,本文會簡單聊到這幾個概念。GlusterFS網上學習資料很多,本文不再贅述,我們仍然主要分析其元數據設計和數據一致性。

GlusterFS使用無元數據結構,亦即“無中心架構”,或“去中心化”,它使用一致性哈希,或者說是DHT(Distributed Hash Table)來定位數據位置。部署好一個GlusterFS集羣,IO節點知悉集羣存儲節點列表,讀寫文件時,以文件名和存儲節點列表爲DHT算法輸入,定位出文件存儲位置。

在集羣無故障時,存儲節點列表固定,DHT算法簡單有效。但在集羣發生節點進出類故障時(比如有存儲節點crash等),DHT應對就頗爲乏力,應對邏輯複雜,且會對業務可用性產生很大影響,因爲存儲節點列表變化,不少文件根據DHT計算的定位也發生變化,會涉及數據挪動,會涉及業務IO需等待恢復IO先行完成。

另一方面,這種無中心元數據結構,應對元數據操作時消耗頗大,比如一個ls,會放大到數個存儲節點去做ls。而一般認爲,文件系統中元數據操作佔比很大,無元結構對這一事實頗爲頭疼。

數據一致性方面,GlusterFS是不提供數據強一致性的。我們數年前有過GlusterFS的開發經驗,split-brain —— 中文稱爲“腦裂” —— 對這一名詞,我們至今印象深刻。

split-brain含義就是數據副本間不一致,比如副本1的內容是ABC,副本2的內容是AB,集羣判定不出誰是合法數據。

我們構造出一個split brain的場景:

  • brick1 down, write fileX
  • brick1 up, brick2 down, write fileX
  • brick1 brick2都up,split brain發生,brick1 brick2相互blame

GlusterFS官方文檔是明確提及這一問題的,參見"Heal info and split-brain resolution” (https://docs.gluster.org/en/latest/Troubleshooting/resolving-splitbrain/)。能感覺出GlusterFS的定位並不是強一致的分佈式文件系統,至此,我們也很能理解爲什麼它主要用於大塊順序IO的視頻或日誌文件存儲,因這類數據文件大,總體文件數目少,性能更偏重於吞吐。且並非關鍵數據,發生split brain之類數據一致性問題後影響較小。

從GlusterFS社區計劃來看,他們也考慮要處理元數據性能問題和數據一致性問題,但我認爲這是兩大核心問題,跟核心架構強相關,要致力於很好解決頗有難度。不過技術無止境,我們頗爲期待

https://www.gluster.org/

CephFS 

Ceph是近年來最成功的分佈式存儲系統,這裏需注意並非說是分佈式文件系統,因爲Ceph有三大應用場景,分別是塊存儲Ceph RBD,對象存儲Ceph RGW,以及文件存儲CephFS。

 

Ceph RBD相信很多人都比較熟悉,因爲在數年前雲計算在風口的時候,OpenStack如日中天,Ceph RBD與OpenStack一拍即合,應用頗廣。

CephFS、RBD、RGW三者的核心都是RADOS,這個模塊負責數據定位,多副本,副本間強一致以及數據恢復等核心功能。RADOS數據定位算法是CRUSH,是支持一定程度用戶可控的哈希算法。RADOS做了多副本寫的事務,保證單次寫的原子性,並通過pglog等機制保證副本間的數據一致性。

我們也曾有Ceph RBD的開發經驗,我們綜合看來,Ceph是分佈式存儲理論和實踐的集大成者。它理論完備,實現上雖代碼龐雜,但模塊比較清晰,代碼質量頗高,非常值得去學習。

理論角度Ceph無可指摘,幾年前,投入Ceph二次開發的公司頗多,但大浪淘沙,只剩下一些研發實力較強的廠商在這方面堅持投入。其原因之一在於Ceph代碼過於繁雜,一般難以全面掌控,優化的效果和投入的資源不完全成正比。

讓我們迴歸“分佈式文件系統”這一主題,回到本文主要討論元數據和數據一致性的視角。

CephFS是有元數據服務的,它稱之爲MDS。CephFS的元數據和數據都是存儲在RADOS中的,從而CephFS的開發思路跟前面提及的MooseFS就很不相同,比如MooseFS要做元數據服務的Leader Follower,而CephFS不需要考慮這些,它的數據通過RADOS天然就可靠、一致地冗餘存儲到集羣中了。簡單來說,CephFS的元數據管理MDS,更像是基於一個穩定數據放置和存儲層(這一層負責通過副本或EC方式確保數據強一致)之上,即RADOS之上,建設一個元數據服務層。這種架構在充分利用RADOS架構優勢的同時,也帶來了一些弊端,我們之前談到,分佈式文件系統中大量操作都和元數據相關,CephFS先訪問 MDS,最終再訪問RADOS中的數據,IO路徑加長,對文件系統性能的影響來看,顯得尤爲明顯。

https://ceph.io/

總結

本文我們概要地討論了常見的幾個開源的分佈式文件系統,主要從元數據和數據一致性兩大角度去分析,我們認爲從理論角度看,目前CephFS是最完備的。

不過,討論一個分佈式文件系統有多種不同的視角,比如大文件備份的應用場景下,MooseFS就比較適合,而如果使用CephFS就太過複雜;HPC場景下,Lustre應用很廣,但換上CephFS也很可能面臨性能降級。所以本文並非是對提及的分佈式文件系統的“筆伐”,而是站在“元數據和數據一致性”視角,討論我們的看法,從而在設計和實現自己的文件系統時,獲得更廣泛的思路。

每個系統都有自己的權衡,都有自己的閃光點,本文不能一一而足,以後有機會再行細緻討論,也歡迎大家留言探討。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章