作者:admin 日期:2023-08-25 瀏覽: 次
主流分布式文件系統(tǒng)對比
分布式文件系統(tǒng)是分布式領(lǐng)域的一個基礎(chǔ)應(yīng)用,其中最著名的毫無疑問是HDFS/GFS。如今該領(lǐng)域已經(jīng)趨向于成熟,但了解它的設(shè)計要點和思想,對我們將來面臨類似場景/問題時,具有借鑒意義。并且,分布式文件系統(tǒng)并非只有HDFS/GFS這一種形態(tài),在它之外,還有其他形態(tài)各異、各有千秋的產(chǎn)品形態(tài),對它們的了解,也對擴展我們的視野有所俾益。本文試圖分析和思考,在分布式文件系統(tǒng)領(lǐng)域,我們要解決哪些問題、有些什么樣的方案、以及各自的選擇依據(jù)。
在幾十年以前,分布式文件系統(tǒng)就已經(jīng)出現(xiàn)了,以Sun在1984年開發(fā)的“Network File System (NFS)”為代表,那時候解決的主要問題,是網(wǎng)絡(luò)形態(tài)的磁盤,把磁盤從主機中獨立出來。這樣不僅可以獲得更大的容量,而且還可以隨時切換主機,還可以實現(xiàn)數(shù)據(jù)共享、備份、容災(zāi)等,因為數(shù)據(jù)是電腦中最重要的資產(chǎn)。NFS的數(shù)據(jù)通信圖如下
部署在主機上的客戶端,通過TCP/IP協(xié)議把文件命令轉(zhuǎn)發(fā)到遠程文件Server上執(zhí)行,整個過程對主機用戶透明。
到了互聯(lián)網(wǎng)時代,流量和數(shù)據(jù)快速增長,分布式文件系統(tǒng)所要解決的主要場景變了,開始需要非常大的磁盤空間,這在磁盤體系上垂直擴容是無法達到的,必須要分布式,同時分布式架構(gòu)下,主機都是可靠性不是非常好的普通服務(wù)器,因此容錯、高可用、持久化、伸縮性等指標,就成為必須要考量的特性。
對一個分布式文件系統(tǒng)而言,有一些特性是必須要滿足的,否則就無法有競爭力。主要如下:
應(yīng)該符合POSIX的文件接口標準,使該系統(tǒng)易于使用,同時對于用戶的遺留系統(tǒng)也無需改造;
對用戶透明,能夠像使用本地文件系統(tǒng)那樣直接使用;
持久化,保證數(shù)據(jù)不會丟失;
具有伸縮性,當數(shù)據(jù)壓力逐漸增長時能順利擴容;
具有可靠的安全機制,保證數(shù)據(jù)安全;
數(shù)據(jù)一致性,只要文件內(nèi)容不發(fā)生變化,什么時候去讀,得到的內(nèi)容應(yīng)該都是一樣的;
還有些特性,是加分項:
支持的空間越大越好;
支持的并發(fā)訪問請求越多越好;
性能越快越好;
硬件資源的利用率越高越合理,就越好;
從業(yè)務(wù)模型和邏輯架構(gòu)上,分布式文件系統(tǒng)需要這幾類組件:
存儲組件:負責(zé)存儲文件數(shù)據(jù),它要保證文件的持久化、副本間數(shù)據(jù)一致、數(shù)據(jù)塊的分配/合并等等;
管理組件:負責(zé)meta信息,即文件數(shù)據(jù)的元信息,包括文件存放在哪臺服務(wù)器上、文件大小、權(quán)限等,除此之外,還要負責(zé)對存儲組件的管理,包括存儲組件所在的服務(wù)器是否正常存活、是否需要數(shù)據(jù)遷移等;
接口組件:提供接口服務(wù)給應(yīng)用使用,形態(tài)包括SDK(Java/C/C++等)、CLI命令行終端、以及支持FUSE掛載機制;
而在部署架構(gòu)上,有著“中心化”和“無中心化”兩種路線分歧,即是否把“管理組件”作為分布式文件系統(tǒng)的中心管理節(jié)點。兩種路線都有很優(yōu)秀的產(chǎn)品,下面分別介紹它們的區(qū)別。
有中心節(jié)點
以GFS為代表,中心節(jié)點負責(zé)文件定位、維護文件meta信息、故障檢測、數(shù)據(jù)遷移等管理控制的職能,下圖是GFS的架構(gòu)圖
GFS架構(gòu)
該圖中GFS master即為GFS的中心節(jié)點,GF chunkserver為GFS的存儲節(jié)點。其操作路徑如下:
Client向中心節(jié)點請求“查詢某個文件的某部分數(shù)據(jù)”
中心節(jié)點返回文件所在的位置(哪臺chunkserver上的哪個文件)以及字節(jié)區(qū)間信息
Client根據(jù)中心節(jié)點返回的信息,向?qū)?yīng)的chunk server直接發(fā)送數(shù)據(jù)讀取的請求
chunk server返回數(shù)據(jù)
在這種方案里,一般中心節(jié)點并不參與真正的數(shù)據(jù)讀寫,而是將文件meta信息返回給Client之后,即由Client與數(shù)據(jù)節(jié)點直接通信。其主要目的是降低中心節(jié)點的負載,防止其成為瓶頸。這種有中心節(jié)點的方案,在各種存儲類系統(tǒng)中得到了廣泛應(yīng)用,因為中心節(jié)點易控制、功能強大。
無中心節(jié)點
以ceph為代表,每個節(jié)點都是自治的、自管理的,整個ceph集群只包含一類節(jié)點,如下圖(最下層紅色的RADOS就是ceph定義的“同時包含meta數(shù)據(jù)和文件數(shù)據(jù)”的節(jié)點)
ceph架構(gòu)
A [Ceph Node] leverages commodity hardware and intelligent daemons, and a [Ceph Storage Cluster] accommodates large numbers of nodes, which communicate with each other to replicate and redistribute data dynamically. Ceph provides an infinitely scalable [Ceph Storage Cluster] based upon RADOS
無中心化的最大優(yōu)點是解決了中心節(jié)點自身的瓶頸,這也就是ceph號稱可以無限向上擴容的原因。但由Client直接和Server通信,那么Client必須要知道,當對某個文件進行操作時,它該訪問集群中的哪個節(jié)點。ceph提供了一個很強大的原創(chuàng)算法來解決這個問題——CRUSH算法。
對于文件系統(tǒng)來說,持久化是根本,只要Client收到了Server保存成功的回應(yīng)之后,數(shù)據(jù)就不應(yīng)該丟失。這主要是通過多副本的方式來解決,但在分布式環(huán)境下,多副本有這幾個問題要面對:
如何保證每個副本的數(shù)據(jù)是一致的?
如何分散副本,以使災(zāi)難發(fā)生時,不至于所有副本都被損壞?
怎么檢測被損壞或數(shù)據(jù)過期的副本,以及如何處理?
該返回哪個副本給Client?
如何保證每個副本的數(shù)據(jù)是一致的
同步寫入是保證副本數(shù)據(jù)一致的最直接的辦法。當Client寫入一個文件的時候,Server會等待所有副本都被成功寫入,再返回給Client。
這種方式簡單、有保障,唯一的缺陷就是性能會受到影響。假設(shè)有3個副本,如果每個副本需要N秒,則可能會阻塞Client 3N秒的時間,有幾種方式,可以對其進行優(yōu)化:
并行寫:由一個副本作為主副本,并行發(fā)送數(shù)據(jù)給其他副本;
鏈式寫:幾個副本組成一個鏈(chain),并不是等內(nèi)容都接受到了再往后傳播,而是像流一樣,邊接收上游傳遞過來的數(shù)據(jù),一邊傳遞給下游;
還有一種方式是采用CAP中所說的W+R>N的方式,比如3副本(N=3)的情況,W=2,R=2,即成功寫入2個就認為成功,讀的時候也要從2個副本中讀。這種方式通過犧牲一定的讀成本,來降低寫成本,同時增加寫入的可用性。這種方式在分布式文件系統(tǒng)中用地比較少。
如何分散副本,以使災(zāi)難發(fā)生時,不至于所有副本都被損壞
這主要避免的是某機房或某城市發(fā)生自然環(huán)境故障的情況,所以有一個副本應(yīng)該分配地比較遠。它的副作用是會帶來這個副本的寫入性能可能會有一定的下降,因為它離Client最遠。所以如果在物理條件上無法保證夠用的網(wǎng)絡(luò)帶寬的話,則讀寫副本的策略上需要做一定考慮??梢詤⒖纪綄懭胫粚?副本、較遠副本異步寫入的方式,同時為了保證一致性,讀取的時候又要注意一些,避免讀取到異步寫入副本的過時數(shù)據(jù)。
怎么檢測被損壞或數(shù)據(jù)過期的副本,以及如何處理
如果有中心節(jié)點,則數(shù)據(jù)節(jié)點定期和中心節(jié)點進行通信,匯報自己的數(shù)據(jù)塊的相關(guān)信息,中心節(jié)點將其與自己維護的信息進行對比。如果某個數(shù)據(jù)塊的checksum不對,則表明該數(shù)據(jù)塊被損壞了;如果某個數(shù)據(jù)塊的version不對,則表明該數(shù)據(jù)塊過期了。
如果沒有中心節(jié)點,以ceph為例,它在自己的節(jié)點集群中維護了一個比較小的monitor集群,數(shù)據(jù)節(jié)點向這個monitor集群匯報自己的情況,由其來判定是否被損壞或過期。
當發(fā)現(xiàn)被損壞或過期副本,將它從meta信息中移除,再重新創(chuàng)建一份新的副本就好了,移除的副本在隨后的回收機制中會被收回。
該返回哪個副本給Client
這里的策略就比較多了,比如round-robin、速度最快的節(jié)點、成功率最高的節(jié)點、CPU資源最空閑的節(jié)點、甚至就固定選第一個作為主節(jié)點,也可以選擇離自己最近的一個,這樣對整體的操作完成時間會有一定節(jié)約。
存儲節(jié)點的伸縮
當在集群中加入一臺新的存儲節(jié)點,則它主動向中心節(jié)點注冊,提供自己的信息,當后續(xù)有創(chuàng)建文件或者給已有文件增加數(shù)據(jù)塊的時候,中心節(jié)點就可以分配到這臺新節(jié)點了,比較簡單。但有一些問題需要考慮:
如何盡量使各存儲節(jié)點的負載相對均衡?
怎樣保證新加入的節(jié)點,不會因短期負載壓力過大而崩塌?

如果需要數(shù)據(jù)遷移,那如何使其對業(yè)務(wù)層透明?
如何盡量使各存儲節(jié)點的負載相對均衡
首先要有評價存儲節(jié)點負載的指標。有多種方式,可以從磁盤空間使用率考慮,也可以從磁盤使用率+CPU使用情況+網(wǎng)絡(luò)流量情況等做綜合判斷。一般來說,磁盤使用率是核心指標。
其次在分配新空間的時候,優(yōu)先選擇資源使用率小的存儲節(jié)點;而對已存在的存儲節(jié)點,如果負載已經(jīng)過載、或者資源使用情況不均衡,則需要做數(shù)據(jù)遷移。
怎樣保證新加入的節(jié)點,不會因短期負載壓力過大而崩塌
當系統(tǒng)發(fā)現(xiàn)當前新加入了一臺存儲節(jié)點,顯然它的資源使用率是最低的,那么所有的寫流量都路由到這臺存儲節(jié)點來,那就可能造成這臺新節(jié)點短期負載過大。因此,在資源分配的時候,需要有預(yù)熱時間,在一個時間段內(nèi),緩慢地將寫壓力路由過來,直到達成新的均衡。
如果需要數(shù)據(jù)遷移,那如何使其對業(yè)務(wù)層透明?
在有中心節(jié)點的情況下,這個工作比較好做,中心節(jié)點就包辦了——判斷哪臺存儲節(jié)點壓力較大,判斷把哪些文件遷移到何處,更新自己的meta信息,遷移過程中的寫入怎么辦,發(fā)生重命名怎么辦。無需上層應(yīng)用來處理。
如果沒有中心節(jié)點,那代價比較大,在系統(tǒng)的整體設(shè)計上,也是要考慮到這種情況,比如ceph,它要采取邏輯位置和物理位置兩層結(jié)構(gòu),對Client暴露的是邏輯層(pool和place group),這個在遷移過程中是不變的,而下層物理層數(shù)據(jù)塊的移動,只是邏輯層所引用的物理塊的地址發(fā)生了變化,在Client看來,邏輯塊的位置并不會發(fā)生改變。
中心節(jié)點的伸縮
如果有中心節(jié)點,還要考慮它的伸縮性。由于中心節(jié)點作為控制中心,是主從模式,那么在伸縮性上就受到比較大的限制,是有上限的,不能超過單臺物理機的規(guī)模。我們可以考慮各種手段,盡量地抬高這個上限。有幾種方式可以考慮:
以大數(shù)據(jù)塊的形式來存儲文件——比如HDFS的數(shù)據(jù)塊的大小是64M,ceph的的數(shù)據(jù)塊的大小是4M,都遠遠超過單機文件系統(tǒng)的4k。它的意義在于大幅減少meta data的數(shù)量,使中心節(jié)點的單機內(nèi)存就能夠支持足夠多的磁盤空間meta信息;
中心節(jié)點采取多級的方式——頂級中心節(jié)點只存儲目錄的meta data,其指定某目錄的文件去哪臺次級總控節(jié)點去找,然后再通過該次級總控節(jié)點找到文件真正的存儲節(jié)點。
中心節(jié)點共享存儲設(shè)備——部署多臺中心節(jié)點,但它們共享同一個存儲外設(shè)/數(shù)據(jù)庫,meta信息都放在這里,中心節(jié)點自身是無狀態(tài)的。這種模式下,中心節(jié)點的請求處理能力大為增強,但性能會受一定影響。iRODS就是采用這種方式。
中心節(jié)點的高可用
中心節(jié)點的高可用,不僅要保證自身應(yīng)用的高可用,還得保證meta data的數(shù)據(jù)高可用。
meta data的高可用主要是數(shù)據(jù)持久化,并且需要備份機制保證不丟。一般方法是增加一個從節(jié)點,主節(jié)點的數(shù)據(jù)實時同步到從節(jié)點上。也有采用共享磁盤,通過raid1的硬件資源來保障高可用。顯然增加從節(jié)點的主備方式更易于部署。
meta data的數(shù)據(jù)持久化策略有幾種方式:
直接保存到存儲引擎上,一般是數(shù)據(jù)庫。直接以文件形式保存到磁盤上,也不是不可以,但因為meta信息是結(jié)構(gòu)化數(shù)據(jù),這樣相當于自己研發(fā)出一套小型數(shù)據(jù)庫來,復(fù)雜化了。
保存日志數(shù)據(jù)到磁盤文件(類似MySQL的binlog或Redis的aof),系統(tǒng)啟動時在內(nèi)存中重建成結(jié)果數(shù)據(jù),提供服務(wù)。修改時先修改磁盤日志文件,然后更新內(nèi)存數(shù)據(jù)。這種方式簡單易用。
當前內(nèi)存服務(wù)+日志文件持久化是主流方式。一是純內(nèi)存操作,效率很高,日志文件的寫也是順序?qū)?;二是不依賴外部組件,獨立部署。
為了解決日志文件會隨著時間增長越來越大的問題,以讓系統(tǒng)能以盡快啟動和恢復(fù),需要輔助以內(nèi)存快照的方式——定期將內(nèi)存dump保存,只保留在dump時刻之后的日志文件。這樣當恢復(fù)時,從最新一次的內(nèi)存dump文件開始,找其對應(yīng)的checkpoint之后的日志文件開始重播。
存儲節(jié)點的高可用
在前面“持久化”章節(jié),在保證數(shù)據(jù)副本不丟失的情況下,也就保證了其的高可用性。
這些年隨著基礎(chǔ)設(shè)施的發(fā)展,局域網(wǎng)內(nèi)千兆甚至萬兆的帶寬已經(jīng)比較普遍,以萬兆計算,每秒傳輸大約1250M字節(jié)的數(shù)據(jù),而SATA磁盤的讀寫速度這些年基本達到瓶頸,在300-500M/s附近,也就是純讀寫的話,網(wǎng)絡(luò)已經(jīng)超過了磁盤的能力,不再是瓶頸了,像NAS網(wǎng)絡(luò)磁盤這些年也開始普及起來。
但這并不代表,沒有必要對讀寫進行優(yōu)化,畢竟網(wǎng)絡(luò)讀寫的速度還是遠慢于內(nèi)存的讀寫。常見的優(yōu)化方法主要有
內(nèi)存中緩存文件內(nèi)容
預(yù)加載數(shù)據(jù)塊,以避免客戶端等待
合并讀寫請求,也就是將單次請求做些積累,以批量方式發(fā)送給Server端
緩存的使用在提高讀寫性能的同時,也會帶來數(shù)據(jù)不一致的問題:
會出現(xiàn)更新丟失的現(xiàn)象。當多個Client在一個時間段內(nèi),先后寫入同一個文件時,先寫入的Client可能會丟失其寫入內(nèi)容,因為可能會被后寫入的Client的內(nèi)容覆蓋掉;
數(shù)據(jù)可見性問題。Client讀取的是自己的緩存,在其過期之前,如果別的Client更新了文件內(nèi)容,它是看不到的;也就是說,在同一時間,不同Client讀取同一個文件,內(nèi)容可能不一致;
這類問題有幾種方法:
文件只讀不改:一旦文件被create了,就只能讀不能修改。這樣Client端的緩存,就不存在不一致的問題。
通過鎖:用鎖的話還要考慮不同的粒度。寫的時候是否允許其他Client讀? 讀的時候是否允許其他Client寫? 這是在性能和一致性之間的權(quán)衡,作為文件系統(tǒng)來說,由于對業(yè)務(wù)并沒有約束性,所以要做出合理的權(quán)衡,比較困難,因此最好是提供不同粒度的鎖,由業(yè)務(wù)端來選擇。但這樣的副作用是,業(yè)務(wù)端的使用成本抬高了。
由于分布式文件存儲系統(tǒng),肯定是一個多客戶端使用、多租戶的一個產(chǎn)品,而它又存儲了可能是很重要的信息,所以安全性是它的重要部分。
主流文件系統(tǒng)的權(quán)限模型有這么幾種:
DAC: 全稱是Discretionary Access Control,就是我們熟悉的Unix類權(quán)限框架,以user-group-privilege為三級體系,其中user就是owner,group包括owner所在group和非owner所在的group、privilege有read、write和execute。這套體系主要是以owner為出發(fā)點,owner允許誰對哪些文件具有什么樣的權(quán)限。
MAC: 全稱是Mandatory Access Control,它是從資源的機密程度來劃分。比如分為“普通”、“機密”、“絕密”這三層,每個用戶可能對應(yīng)不同的機密閱讀權(quán)限。這種權(quán)限體系起源于安全機構(gòu)或軍隊的系統(tǒng)中,會比較常見。它的權(quán)限是由管理員來控制和設(shè)定的。Linux中的SELinux就是MAC的一種實現(xiàn),為了彌補DAC的缺陷和安全風(fēng)險而提供出來。關(guān)于SELinux所解決的問題可以參考What is SELinux?
RBAC: 全稱是Role Based Access Control,是基于角色(role)建立的權(quán)限體系。角色擁有什么樣的資源權(quán)限,用戶歸到哪個角色,這對應(yīng)企業(yè)/公司的組織機構(gòu)非常合適。RBAC也可以具體化,就演變成DAC或MAC的權(quán)限模型。
市面上的分布式文件系統(tǒng)有不同的選擇,像ceph就提供了類似DAC但又略有區(qū)別的權(quán)限體系,Hadoop自身就是依賴于操作系統(tǒng)的權(quán)限框架,同時其生態(tài)圈內(nèi)有Apache Sentry提供了基于RBAC的權(quán)限體系來做補充。
空間分配
有連續(xù)空間和鏈表空間兩種。連續(xù)空間的優(yōu)勢是讀寫快,按順序即可,劣勢是造成磁盤碎片,更麻煩的是,隨著連續(xù)的大塊磁盤空間被分配滿而必須尋找空洞時,連續(xù)分配需要提前知道待寫入文件的大小,以便找到合適大小的空間,而待寫入文件的大小,往往又是無法提前知道的(比如可編輯的word文檔,它的內(nèi)容可以隨時增大);
而鏈表空間的優(yōu)勢是磁盤碎片很少,劣勢是讀寫很慢,尤其是隨機讀,要從鏈表首個文件塊一個一個地往下找。為了解決這個問題,出現(xiàn)了索引表——把文件和數(shù)據(jù)塊的對應(yīng)關(guān)系也保存一份,存在索引節(jié)點中(一般稱為i節(jié)點),操作系統(tǒng)會將i節(jié)點加載到內(nèi)存,從而程序隨機尋找數(shù)據(jù)塊時,在內(nèi)存中就可以完成了。通過這種方式來解決磁盤鏈表的劣勢,如果索引節(jié)點的內(nèi)容太大,導(dǎo)致內(nèi)存無法加載,還有可能形成多級索引結(jié)構(gòu)。
文件刪除
實時刪除還是延時刪除? 實時刪除的優(yōu)勢是可以快速釋放磁盤空間;延時刪除只是在刪除動作執(zhí)行的時候,置個標識位,后續(xù)在某個時間點再來批量刪除,它的優(yōu)勢是文件仍然可以階段性地保留,最大程度地避免了誤刪除,缺點是磁盤空間仍然被占著。在分布式文件系統(tǒng)中,磁盤空間都是比較充裕的資源,因此幾乎都采用邏輯刪除,以對數(shù)據(jù)可以進行恢復(fù),同時在一段時間之后(可能是2天或3天,這參數(shù)一般都可配置),再對被刪除的資源進行回收。
怎么回收被刪除或無用的數(shù)據(jù)? 可以從文件的meta信息出發(fā)——如果meta信息的“文件-數(shù)據(jù)塊”映射表中包含了某個數(shù)據(jù)塊,則它就是有用的;如果不包含,則表明該數(shù)據(jù)塊已經(jīng)是無效的了。所以,刪除文件,其實是刪除meta中的“文件-數(shù)據(jù)塊”映射信息(如果要保留一段時間,則是把這映射信息移到另外一個地方去)。
面向小文件的分布式文件系統(tǒng)
有很多這樣的場景,比如電商——那么多的商品圖片、個人頭像,比如社交網(wǎng)站——那么多的照片,它們具有的特性,可以簡單歸納下:
每個文件都不大
數(shù)量特別巨大
讀多寫少
不會修改針對這種業(yè)務(wù)場景,主流的實現(xiàn)方式是仍然是以大數(shù)據(jù)塊的形式存儲,小文件以邏輯存儲的方式存在,即文件meta信息記錄其是在哪個大數(shù)據(jù)塊上,以及在該數(shù)據(jù)塊上的offset和length是多少,形成一個邏輯上的獨立文件。這樣既復(fù)用了大數(shù)據(jù)塊系統(tǒng)的優(yōu)勢和技術(shù)積累,又減少了meta信息。
文件指紋和去重
文件指紋就是根據(jù)文件內(nèi)容,經(jīng)過算法,計算出文件的唯一標識。如果兩個文件的指紋相同,則文件內(nèi)容相同。在使用網(wǎng)絡(luò)云盤的時候,發(fā)現(xiàn)有時候上傳文件非常地快,就是文件指紋發(fā)揮作用。云盤服務(wù)商通過判斷該文件的指紋,發(fā)現(xiàn)之前已經(jīng)有人上傳過了,則不需要真的上傳該文件,只要增加一個引用即可。在文件系統(tǒng)中,通過文件指紋可以用來去重、也可以用來判斷文件內(nèi)容是否損壞、或者對比文件副本內(nèi)容是否一致,是一個基礎(chǔ)組件。
文件指紋的算法也比較多,有熟悉的md5、sha256、也有g(shù)oogle專門針對文本領(lǐng)域的simhash和minhash等。
分布式文件系統(tǒng)內(nèi)容龐雜,要考慮的問題遠不止上面所說的這些,其具體實現(xiàn)也更為復(fù)雜。本文只是盡量從分布式文件系統(tǒng)所要考慮的問題出發(fā),給予一個簡要的分析和設(shè)計,如果將來遇到類似的場景需要解決,可以想到“有這種解決方案”,然后再來深入研究。
同時,市面上也是存在多種分布式文件系統(tǒng)的形態(tài),下面就是有研究小組曾經(jīng)對常見的幾種分布式文件系統(tǒng)的設(shè)計比較
幾種分布式文件系統(tǒng)的比較
從這里也可以看到,選擇其實很多,并不是GFS論文中的方式就是最好的。在不同的業(yè)務(wù)場景中,也可以有更多的選擇策略。