主流分佈式文件系統對比

本文較長,建議細細品讀,必有不一樣的收穫。算法

1、概述

分佈式文件系統是分佈式領域的一個基礎應用,其中最著名的毫無疑問是 HDFS/GFS。現在該領域已經趨向於成熟,但瞭解它的設計要點和思想,對咱們未來面臨相似場景/問題時,具備借鑑意義。數據庫

而且,分佈式文件系統並不是只有 HDFS/GFS 這一種形態,在它以外,還有其餘形態萬千、各有千秋的產品形態,對它們的瞭解,也對擴展咱們的視野有所俾益。緩存

本文試圖分析和思考,在分佈式文件系統領域,咱們要解決哪些問題、有些什麼樣的方案、以及各自的選擇依據。安全

2、過去的樣子

在幾十年之前,分佈式文件系統就已經出現了,以 Sun 在 1984 年開發的「Network File System (NFS)」爲表明,那時候解決的主要問題,是網絡形態的磁盤,把磁盤從主機中獨立出來。性能優化

這樣不只能夠得到更大的容量,並且還能夠隨時切換主機,還能夠實現數據共享、備份、容災等,由於數據是電腦中最重要的資產。NFS 的數據通訊圖以下:服務器

圖片

部署在主機上的客戶端,經過 TCP/IP 協議把文件命令轉發到遠程文件 Server 上執行,整個過程對主機用戶透明。網絡

到了互聯網時代,流量和數據快速增加,分佈式文件系統所要解決的主要場景變了,開始須要很是大的磁盤空間,這在磁盤體系上垂直擴容是沒法達到的,必需要分佈式,同時分佈式架構下,主機都是可靠性不是很是好的普通服務器,所以容錯、高可用、持久化、伸縮性等指標,就成爲必需要考量的特性。架構

3、對分佈式文件系統的要求

對一個分佈式文件系統而言,有一些特性是必需要知足的,不然就沒法有競爭力。主要以下:併發

  • 應該符合 POSIX 的文件接口標準,使該系統易於使用,同時對於用戶的遺留系統也無需改造;
  • 對用戶透明,可以像使用本地文件系統那樣直接使用;
  • 持久化,保證數據不會丟失;
  • 具備伸縮性,當數據壓力逐漸增加時能順利擴容;
  • 具備可靠的安全機制,保證數據安全;
  • 數據一致性,只要文件內容不發生變化,何時去讀,獲得的內容應該都是同樣的。

除此以外,還有些特性是分佈式加分項,具體以下:框架

  • 支持的空間越大越好;
  • 支持的併發訪問請求越多越好;
  • 性能越快越好;
  • 硬件資源的利用率越高越合理,就越好。

4、架構模型

從業務模型和邏輯架構上,分佈式文件系統須要這幾類組件:

  • 存儲組件:負責存儲文件數據,它要保證文件的持久化、副本間數據一致、數據塊的分配 / 合併等等;
  • 管理組件:負責 meta 信息,即文件數據的元信息,包括文件存放在哪臺服務器上、文件大小、權限等,除此以外,還要負責對存儲組件的管理,包括存儲組件所在的服務器是否正常存活、是否須要數據遷移等;
  • 接口組件:提供接口服務給應用使用,形態包括 SDK(Java/C/C++ 等)、CLI 命令行終端、以及支持 FUSE 掛載機制。

而在部署架構上,有着「中心化」和「無中心化」兩種路線分歧,便是否把「管理組件」做爲分佈式文件系統的中心管理節點。兩種路線都有很優秀的產品,下面分別介紹它們的區別。

一、有中心節點

以 GFS 爲表明,中心節點負責文件定位、維護文件 meta 信息、故障檢測、數據遷移等管理控制的職能,下圖是 GFS 的架構圖:

圖片

該圖中GFS master 即爲 GFS 的中心節點,GF chunkserver 爲 GFS 的存儲節點。其操做路徑以下:

  • Client 向中心節點請求「查詢某個文件的某部分數據」;
  • 中心節點返回文件所在的位置 (哪臺 chunkserver 上的哪一個文件) 以及字節區間信息;
  • Client 根據中心節點返回的信息,向對應的 chunk server 直接發送數據讀取的請求;
  • chunk server 返回數據。

在這種方案裏,通常中心節點並不參與真正的數據讀寫,而是將文件 meta 信息返回給 Client 以後,即由 Client 與數據節點直接通訊。其主要目的是下降中心節點的負載,防止其成爲瓶頸。這種有中心節點的方案,在各類存儲類系統中獲得了普遍應用,由於中心節點易控制、功能強大。

二、無中心節點

以ceph爲表明,每一個節點都是自治的、自管理的,整個 ceph 集羣只包含一類節點,以下圖 (最下層紅色的 RADOS 就是 ceph 定義的「同時包含 meta 數據和文件數據」的節點)。

圖片

無中心化的最大優勢是解決了中心節點自身的瓶頸,這也就是 ceph 號稱能夠無限向上擴容的緣由。但由 Client 直接和 Server 通訊,那麼 Client 必需要知道,當對某個文件進行操做時,它該訪問集羣中的哪一個節點。ceph 提供了一個很強大的原創算法來解決這個問題——CRUSH 算法。

5、持久化

對於文件系統來講,持久化是根本,只要 Client 收到了 Server 保存成功的迴應以後,數據就不該該丟失。這主要是經過多副本的方式來解決,但在分佈式環境下,多副本有這幾個問題要面對。

  • 如何保證每一個副本的數據是一致的?
  • 如何分散副本,以使災難發生時,不至於全部副本都被損壞?
  • 怎麼檢測被損壞或數據過時的副本,以及如何處理?
  • 該返回哪一個副本給 Client?
一、如何保證每一個副本的數據是一致的?

同步寫入是保證副本數據一致的最直接的辦法。當 Client 寫入一個文件的時候,Server 會等待全部副本都被成功寫入,再返回給 Client。

這種方式簡單、有保障,惟一的缺陷就是性能會受到影響。假設有 3 個副本,若是每一個副本須要N秒,則可能會阻塞 Client 3N 秒的時間,有幾種方式,能夠對其進行優化:

  • 並行寫:由一個副本做爲主副本,並行發送數據給其餘副本;
  • 鏈式寫:幾個副本組成一個鏈 (chain),並非等內容都接受到了再日後傳播,而是像流同樣,邊接收上游傳遞過來的數據,一邊傳遞給下游。

還有一種方式是採用 CAP 中所說的 W+R>N 的方式,好比 3 副本 (N=3) 的狀況,W=2,R=2,即成功寫入 2 個就認爲成功,讀的時候也要從 2 個副本中讀。這種方式經過犧牲必定的讀成本,來下降寫成本,同時增長寫入的可用性。這種方式在分佈式文件系統中用地比較少。

二、如何分散副本,以使災難發生時,不至於全部副本都被損壞?

這主要避免的是某機房或某城市發生天然環境故障的狀況,因此有一個副本應該分配地比較遠。它的反作用是會帶來這個副本的寫入性能可能會有必定的降低,由於它離 Client 最遠。因此若是在物理條件上沒法保證夠用的網絡帶寬的話,則讀寫副本的策略上須要作必定考慮。

能夠參考同步寫入只寫 2 副本、較遠副本異步寫入的方式,同時爲了保證一致性,讀取的時候又要注意一些,避免讀取到異步寫入副本的過期數據。

三、怎麼檢測被損壞或數據過時的副本,以及如何處理?

若是有中心節點,則數據節點按期和中心節點進行通訊,彙報本身的數據塊的相關信息,中心節點將其與本身維護的信息進行對比。若是某個數據塊的 checksum 不對,則代表該數據塊被損壞了;若是某個數據塊的 version 不對,則代表該數據塊過時了。

若是沒有中心節點,以 ceph 爲例,它在本身的節點集羣中維護了一個比較小的 monitor 集羣,數據節點向這個 monitor 集羣彙報本身的狀況,由其來斷定是否被損壞或過時。

當發現被損壞或過時副本,將它從 meta 信息中移除,再從新建立一份新的副本就行了,移除的副本在隨後的回收機制中會被收回。

四、該返回哪一個副本給 Client?

這裏的策略就比較多了,好比 round-robin、速度最快的節點、成功率最高的節點、CPU 資源最空閒的節點、甚至就固定選第一個做爲主節點,也能夠選擇離本身最近的一個,這樣對總體的操做完成時間會有必定節約。

6、伸縮性

一、存儲節點的伸縮

當在集羣中加入一臺新的存儲節點,則它主動向中心節點註冊,提供本身的信息,當後續有建立文件或者給已有文件增長數據塊的時候,中心節點就能夠分配到這臺新節點了,比較簡單。但有一些問題須要考慮。

  • 如何儘可能使各存儲節點的負載相對均衡?
  • 怎樣保證新加入的節點,不會因短時間負載壓力過大而崩塌?
  • 若是須要數據遷移,那如何使其對業務層透明?
  • 1)如何儘可能使各存儲節點的負載相對均衡?

首先要有評價存儲節點負載的指標。有多種方式,能夠從磁盤空間使用率考慮,也能夠從磁盤使用率 +CPU 使用狀況 + 網絡流量狀況等作綜合判斷。通常來講,磁盤使用率是核心指標。

其次在分配新空間的時候,優先選擇資源使用率小的存儲節點;而對已存在的存儲節點,若是負載已通過載、或者資源使用狀況不均衡,則須要作數據遷移。

  • 2)怎樣保證新加入的節點,不會因短時間負載壓力過大而崩塌?

當系統發現當前新加入了一臺存儲節點,顯然它的資源使用率是最低的,那麼全部的寫流量都路由到這臺存儲節點來,那就可能形成這臺新節點短時間負載過大。所以,在資源分配的時候,須要有預熱時間,在一個時間段內,緩慢地將寫壓力路由過來,直到達成新的均衡。

  • 3)若是須要數據遷移,那如何使其對業務層透明?

在有中心節點的狀況下,這個工做比較好作,中心節點就包辦了——判斷哪臺存儲節點壓力較大,判斷把哪些文件遷移到何處,更新本身的 meta 信息,遷移過程當中的寫入怎麼辦,發生重命名怎麼辦。無需上層應用來處理。

若是沒有中心節點,那代價比較大,在系統的總體設計上,也是要考慮到這種狀況,好比ceph,它要採起邏輯位置和物理位置兩層結構,對Client暴露的是邏輯層 (pool 和 place group),這個在遷移過程當中是不變的,而下層物理層數據塊的移動,只是邏輯層所引用的物理塊的地址發生了變化,在Client看來,邏輯塊的位置並不會發生改變。

二、中心節點的伸縮

若是有中心節點,還要考慮它的伸縮性。因爲中心節點做爲控制中心,是主從模式,那麼在伸縮性上就受到比較大的限制,是有上限的,不能超過單臺物理機的規模。咱們能夠考慮各類手段,儘可能地擡高這個上限。有幾種方式能夠考慮:

  • 以大數據塊的形式來存儲文件——好比 HDFS 的數據塊的大小是 64M,ceph 的的數據塊的大小是 4M,都遠遠超過單機文件系統的 4k。它的意義在於大幅減小 meta data 的數量,使中心節點的單機內存就可以支持足夠多的磁盤空間 meta 信息。
  • 中心節點採起多級的方式——頂級中心節點只存儲目錄的 meta data,其指定某目錄的文件去哪臺次級總控節點去找,而後再經過該次級總控節點找到文件真正的存儲節點;
  • 中心節點共享存儲設備——部署多臺中心節點,但它們共享同一個存儲外設 / 數據庫,meta 信息都放在這裏,中心節點自身是無狀態的。這種模式下,中心節點的請求處理能力大爲加強,但性能會受必定影響。iRODS 就是採用這種方式。

7、高可用性

一、中心節點的高可用

中心節點的高可用,不只要保證自身應用的高可用,還得保證 meta data 的數據高可用。

meta data 的高可用主要是數據持久化,而且須要備份機制保證不丟。通常方法是增長一個從節點,主節點的數據實時同步到從節點上。也有采用共享磁盤,經過 raid1 的硬件資源來保障高可用。顯然增長從節點的主備方式更易於部署。

meta data 的數據持久化策略有如下幾種方式:

  • 直接保存到存儲引擎上,通常是數據庫。直接以文件形式保存到磁盤上,也不是不能夠,但由於 meta 信息是結構化數據,這樣至關於本身研發出一套小型數據庫來,複雜化了。
  • 保存日誌數據到磁盤文件 (相似 MySQL 的 binlog 或 Redis 的 aof),系統啓動時在內存中重建成結果數據,提供服務。修改時先修改磁盤日誌文件,而後更新內存數據。這種方式簡單易用。

當前內存服務 + 日誌文件持久化是主流方式。一是純內存操做,效率很高,日誌文件的寫也是順序寫;二是不依賴外部組件,獨立部署。

爲了解決日誌文件會隨着時間增加愈來愈大的問題,以讓系統能以儘快啓動和恢復,須要輔助之內存快照的方式——按期將內存 dump 保存,只保留在 dump 時刻以後的日誌文件。這樣當恢復時,從最新一次的內存 dump 文件開始,找其對應的 checkpoint 以後的日誌文件開始重播。

二、存儲節點的高可用

在前面「持久化」章節,在保證數據副本不丟失的狀況下,也就保證了其的高可用性。

8、性能優化和緩存一致性

這些年隨着基礎設施的發展,局域網內千兆甚至萬兆的帶寬已經比較廣泛,以萬兆計算,每秒傳輸大約 1250M 字節的數據,而 SATA 磁盤的讀寫速度這些年基本達到瓶頸,在 300-500M/s 附近,也就是純讀寫的話,網絡已經超過了磁盤的能力,再也不是瓶頸了,像 NAS 網絡磁盤這些年也開始普及起來。

但這並不表明,沒有必要對讀寫進行優化,畢竟網絡讀寫的速度仍是遠慢於內存的讀寫。常見的優化方法主要有:

  • 內存中緩存文件內容;
  • 預加載數據塊,以免客戶端等待;
  • 合併讀寫請求,也就是將單次請求作些積累,以批量方式發送給 Server 端。

緩存的使用在提升讀寫性能的同時,也會帶來數據不一致的問題:

  • 會出現更新丟失的現象。當多個 Client 在一個時間段內,前後寫入同一個文件時,先寫入的 Client 可能會丟失其寫入內容,由於可能會被後寫入的 Client 的內容覆蓋掉;
  • 數據可見性問題。Client 讀取的是本身的緩存,在其過時以前,若是別的 Client 更新了文件內容,它是看不到的;也就是說,在同一時間,不一樣 Client 讀取同一個文件,內容可能不一致。

這類問題有幾種方法:

  • 文件只讀不改:一旦文件被 create 了,就只能讀不能修改。這樣 Client 端的緩存,就不存在不一致的問題;
  • 經過鎖:用鎖的話還要考慮不一樣的粒度。寫的時候是否容許其餘 Client 讀? 讀的時候是否容許其餘 Client 寫? 這是在性能和一致性之間的權衡,做爲文件系統來講,因爲對業務並無約束性,因此要作出合理的權衡,比較困難,所以最好是提供不一樣粒度的鎖,由業務端來選擇。但這樣的反作用是,業務端的使用成本擡高了。

9、安全性

因爲分佈式文件存儲系統,確定是一個多客戶端使用、多租戶的一個產品,而它又存儲了多是很重要的信息,因此安全性是它的重要部分。

主流文件系統的權限模型有如下這麼幾種:

  • DAC:全稱是Discretionary Access Control,就是咱們熟悉的 Unix 類權限框架,以 user-group-privilege 爲三級體系,其中 user 就是 owner,group 包括 owner 所在 group 和非 owner 所在的 group、privilege 有 read、write 和 execute。這套體系主要是以 owner 爲出發點,owner 容許誰對哪些文件具備什麼樣的權限。
  • MAC:全稱是 Mandatory Access Control,它是從資源的機密程度來劃分。好比分爲「普通」、「機密」、「絕密」這三層,每一個用戶可能對應不一樣的機密閱讀權限。這種權限體系起源於安全機構或軍隊的系統中,會比較常見。它的權限是由管理員來控制和設定的。Linux 中的 SELinux 就是 MAC 的一種實現,爲了彌補 DAC 的缺陷和安全風險而提供出來。關於 SELinux 所解決的問題能夠參考 What is SELinux?
  • RBAC:全稱是 Role Based Access Control,是基於角色 (role) 創建的權限體系。角色擁有什麼樣的資源權限,用戶歸到哪一個角色,這對應企業 / 公司的組織機構很是合適。RBAC 也能夠具體化,就演變成 DAC 或 MAC 的權限模型。

市面上的分佈式文件系統有不一樣的選擇,像 ceph 就提供了相似 DAC 但又略有區別的權限體系,Hadoop 自身就是依賴於操做系統的權限框架,同時其生態圈內有 Apache Sentry 提供了基於 RBAC 的權限體系來作補充。

10、其餘

一、空間分配

有連續空間和鏈表空間兩種。連續空間的優點是讀寫快,按順序便可,劣勢是形成磁盤碎片,更麻煩的是,隨着連續的大塊磁盤空間被分配滿而必須尋找空洞時,連續分配須要提早知道待寫入文件的大小,以便找到合適大小的空間,而待寫入文件的大小,每每又是沒法提早知道的 (好比可編輯的 word 文檔,它的內容能夠隨時增大);

而鏈表空間的優點是磁盤碎片不多,劣勢是讀寫很慢,尤爲是隨機讀,要從鏈表首個文件塊一個一個地往下找。

爲了解決這個問題,出現了索引表——把文件和數據塊的對應關係也保存一份,存在索引節點中 (通常稱爲 i 節點),操做系統會將 i 節點加載到內存,從而程序隨機尋找數據塊時,在內存中就能夠完成了。經過這種方式來解決磁盤鏈表的劣勢,若是索引節點的內容太大,致使內存沒法加載,還有可能造成多級索引結構。

二、文件刪除

實時刪除仍是延時刪除? 實時刪除的優點是能夠快速釋放磁盤空間;延時刪除只是在刪除動做執行的時候,置個標識位,後續在某個時間點再來批量刪除,它的優點是文件仍然能夠階段性地保留,最大程度地避免了誤刪除,缺點是磁盤空間仍然被佔着。在分佈式文件系統中,磁盤空間都是比較充裕的資源,所以幾乎都採用邏輯刪除,以對數據能夠進行恢復,同時在一段時間以後 (多是 2 天或 3 天,這參數通常均可配置),再對被刪除的資源進行回收。

怎麼回收被刪除或無用的數據? 能夠從文件的 meta 信息出發——若是 meta 信息的「文件 - 數據塊」映射表中包含了某個數據塊,則它就是有用的;若是不包含,則代表該數據塊已是無效的了。因此,刪除文件,實際上是刪除 meta 中的「文件 - 數據塊」映射信息 (若是要保留一段時間,則是把這映射信息移到另一個地方去)。

三、面向小文件的分佈式文件系統

有不少這樣的場景,好比電商——那麼多的商品圖片、我的頭像,好比社交網站——那麼多的照片,它們具備的特性,能夠簡單概括下:

  • 每一個文件都不大;
  • 數量特別巨大;
  • 讀多寫少;
  • 不會修改。

針對這種業務場景,主流的實現方式是仍然是以大數據塊的形式存儲,小文件以邏輯存儲的方式存在,即文件 meta 信息記錄其是在哪一個大數據塊上,以及在該數據塊上的 offset 和 length 是多少,造成一個邏輯上的獨立文件。這樣既複用了大數據塊系統的優點和技術積累,又減小了 meta 信息。

四、文件指紋和去重

文件指紋就是根據文件內容,通過算法,計算出文件的惟一標識。若是兩個文件的指紋相同,則文件內容相同。在使用網絡雲盤的時候,發現有時候上傳文件很是地快,就是文件指紋發揮做用。雲盤服務商經過判斷該文件的指紋,發現以前已經有人上傳過了,則不須要真的上傳該文件,只要增長一個引用便可。在文件系統中,經過文件指紋能夠用來去重、也能夠用來判斷文件內容是否損壞、或者對比文件副本內容是否一致,是一個基礎組件。

文件指紋的算法也比較多,有熟悉的 md五、sha25六、也有 google 專門針對文本領域的 simhash 和 minhash 等。

11、總結

分佈式文件系統內容龐雜,要考慮的問題遠不止上面所說的這些,其具體實現也更爲複雜。本文只是儘可能從分佈式文件系統所要考慮的問題出發,給予一個簡要的分析和設計,若是未來遇到相似的場景須要解決,能夠想到「有這種解決方案」,而後再來深刻研究。

同時,市面上也是存在多種分佈式文件系統的形態,下面就是有研究小組曾經對常見的幾種分佈式文件系統的設計比較。

圖片

從這裏也能夠看到,選擇其實不少,並非 GFS 論文中的方式就是最好的。在不一樣的業務場景中,也能夠有更多的選擇策略。

來源:https://www.jianshu.com/p/fc0...

相關文章
相關標籤/搜索