本文較長,建議細細品讀,必有不一樣的收穫。算法
分佈式文件系統是分佈式領域的一個基礎應用,其中最著名的毫無疑問是 HDFS/GFS。現在該領域已經趨向於成熟,但瞭解它的設計要點和思想,對咱們未來面臨相似場景/問題時,具備借鑑意義。數據庫
而且,分佈式文件系統並不是只有 HDFS/GFS 這一種形態,在它以外,還有其餘形態萬千、各有千秋的產品形態,對它們的瞭解,也對擴展咱們的視野有所俾益。緩存
本文試圖分析和思考,在分佈式文件系統領域,咱們要解決哪些問題、有些什麼樣的方案、以及各自的選擇依據。安全
在幾十年之前,分佈式文件系統就已經出現了,以 Sun 在 1984 年開發的「Network File System (NFS)」爲表明,那時候解決的主要問題,是網絡形態的磁盤,把磁盤從主機中獨立出來。性能優化
這樣不只能夠得到更大的容量,並且還能夠隨時切換主機,還能夠實現數據共享、備份、容災等,由於數據是電腦中最重要的資產。NFS 的數據通訊圖以下:服務器
部署在主機上的客戶端,經過 TCP/IP 協議把文件命令轉發到遠程文件 Server 上執行,整個過程對主機用戶透明。網絡
到了互聯網時代,流量和數據快速增加,分佈式文件系統所要解決的主要場景變了,開始須要很是大的磁盤空間,這在磁盤體系上垂直擴容是沒法達到的,必需要分佈式,同時分佈式架構下,主機都是可靠性不是很是好的普通服務器,所以容錯、高可用、持久化、伸縮性等指標,就成爲必需要考量的特性。架構
對一個分佈式文件系統而言,有一些特性是必需要知足的,不然就沒法有競爭力。主要以下:併發
除此以外,還有些特性是分佈式加分項,具體以下:框架
從業務模型和邏輯架構上,分佈式文件系統須要這幾類組件:
而在部署架構上,有着「中心化」和「無中心化」兩種路線分歧,便是否把「管理組件」做爲分佈式文件系統的中心管理節點。兩種路線都有很優秀的產品,下面分別介紹它們的區別。
以 GFS 爲表明,中心節點負責文件定位、維護文件 meta 信息、故障檢測、數據遷移等管理控制的職能,下圖是 GFS 的架構圖:
該圖中GFS master 即爲 GFS 的中心節點,GF chunkserver 爲 GFS 的存儲節點。其操做路徑以下:
在這種方案裏,通常中心節點並不參與真正的數據讀寫,而是將文件 meta 信息返回給 Client 以後,即由 Client 與數據節點直接通訊。其主要目的是下降中心節點的負載,防止其成爲瓶頸。這種有中心節點的方案,在各類存儲類系統中獲得了普遍應用,由於中心節點易控制、功能強大。
以ceph爲表明,每一個節點都是自治的、自管理的,整個 ceph 集羣只包含一類節點,以下圖 (最下層紅色的 RADOS 就是 ceph 定義的「同時包含 meta 數據和文件數據」的節點)。
無中心化的最大優勢是解決了中心節點自身的瓶頸,這也就是 ceph 號稱能夠無限向上擴容的緣由。但由 Client 直接和 Server 通訊,那麼 Client 必需要知道,當對某個文件進行操做時,它該訪問集羣中的哪一個節點。ceph 提供了一個很強大的原創算法來解決這個問題——CRUSH 算法。
對於文件系統來講,持久化是根本,只要 Client 收到了 Server 保存成功的迴應以後,數據就不該該丟失。這主要是經過多副本的方式來解決,但在分佈式環境下,多副本有這幾個問題要面對。
同步寫入是保證副本數據一致的最直接的辦法。當 Client 寫入一個文件的時候,Server 會等待全部副本都被成功寫入,再返回給 Client。
這種方式簡單、有保障,惟一的缺陷就是性能會受到影響。假設有 3 個副本,若是每一個副本須要N秒,則可能會阻塞 Client 3N 秒的時間,有幾種方式,能夠對其進行優化:
還有一種方式是採用 CAP 中所說的 W+R>N 的方式,好比 3 副本 (N=3) 的狀況,W=2,R=2,即成功寫入 2 個就認爲成功,讀的時候也要從 2 個副本中讀。這種方式經過犧牲必定的讀成本,來下降寫成本,同時增長寫入的可用性。這種方式在分佈式文件系統中用地比較少。
這主要避免的是某機房或某城市發生天然環境故障的狀況,因此有一個副本應該分配地比較遠。它的反作用是會帶來這個副本的寫入性能可能會有必定的降低,由於它離 Client 最遠。因此若是在物理條件上沒法保證夠用的網絡帶寬的話,則讀寫副本的策略上須要作必定考慮。
能夠參考同步寫入只寫 2 副本、較遠副本異步寫入的方式,同時爲了保證一致性,讀取的時候又要注意一些,避免讀取到異步寫入副本的過期數據。
若是有中心節點,則數據節點按期和中心節點進行通訊,彙報本身的數據塊的相關信息,中心節點將其與本身維護的信息進行對比。若是某個數據塊的 checksum 不對,則代表該數據塊被損壞了;若是某個數據塊的 version 不對,則代表該數據塊過時了。
若是沒有中心節點,以 ceph 爲例,它在本身的節點集羣中維護了一個比較小的 monitor 集羣,數據節點向這個 monitor 集羣彙報本身的狀況,由其來斷定是否被損壞或過時。
當發現被損壞或過時副本,將它從 meta 信息中移除,再從新建立一份新的副本就行了,移除的副本在隨後的回收機制中會被收回。
這裏的策略就比較多了,好比 round-robin、速度最快的節點、成功率最高的節點、CPU 資源最空閒的節點、甚至就固定選第一個做爲主節點,也能夠選擇離本身最近的一個,這樣對總體的操做完成時間會有必定節約。
當在集羣中加入一臺新的存儲節點,則它主動向中心節點註冊,提供本身的信息,當後續有建立文件或者給已有文件增長數據塊的時候,中心節點就能夠分配到這臺新節點了,比較簡單。但有一些問題須要考慮。
首先要有評價存儲節點負載的指標。有多種方式,能夠從磁盤空間使用率考慮,也能夠從磁盤使用率 +CPU 使用狀況 + 網絡流量狀況等作綜合判斷。通常來講,磁盤使用率是核心指標。
其次在分配新空間的時候,優先選擇資源使用率小的存儲節點;而對已存在的存儲節點,若是負載已通過載、或者資源使用狀況不均衡,則須要作數據遷移。
當系統發現當前新加入了一臺存儲節點,顯然它的資源使用率是最低的,那麼全部的寫流量都路由到這臺存儲節點來,那就可能形成這臺新節點短時間負載過大。所以,在資源分配的時候,須要有預熱時間,在一個時間段內,緩慢地將寫壓力路由過來,直到達成新的均衡。
在有中心節點的狀況下,這個工做比較好作,中心節點就包辦了——判斷哪臺存儲節點壓力較大,判斷把哪些文件遷移到何處,更新本身的 meta 信息,遷移過程當中的寫入怎麼辦,發生重命名怎麼辦。無需上層應用來處理。
若是沒有中心節點,那代價比較大,在系統的總體設計上,也是要考慮到這種狀況,好比ceph,它要採起邏輯位置和物理位置兩層結構,對Client暴露的是邏輯層 (pool 和 place group),這個在遷移過程當中是不變的,而下層物理層數據塊的移動,只是邏輯層所引用的物理塊的地址發生了變化,在Client看來,邏輯塊的位置並不會發生改變。
若是有中心節點,還要考慮它的伸縮性。因爲中心節點做爲控制中心,是主從模式,那麼在伸縮性上就受到比較大的限制,是有上限的,不能超過單臺物理機的規模。咱們能夠考慮各類手段,儘可能地擡高這個上限。有幾種方式能夠考慮:
7、高可用性
中心節點的高可用,不只要保證自身應用的高可用,還得保證 meta data 的數據高可用。
meta data 的高可用主要是數據持久化,而且須要備份機制保證不丟。通常方法是增長一個從節點,主節點的數據實時同步到從節點上。也有采用共享磁盤,經過 raid1 的硬件資源來保障高可用。顯然增長從節點的主備方式更易於部署。
meta data 的數據持久化策略有如下幾種方式:
當前內存服務 + 日誌文件持久化是主流方式。一是純內存操做,效率很高,日誌文件的寫也是順序寫;二是不依賴外部組件,獨立部署。
爲了解決日誌文件會隨着時間增加愈來愈大的問題,以讓系統能以儘快啓動和恢復,須要輔助之內存快照的方式——按期將內存 dump 保存,只保留在 dump 時刻以後的日誌文件。這樣當恢復時,從最新一次的內存 dump 文件開始,找其對應的 checkpoint 以後的日誌文件開始重播。
在前面「持久化」章節,在保證數據副本不丟失的狀況下,也就保證了其的高可用性。
這些年隨着基礎設施的發展,局域網內千兆甚至萬兆的帶寬已經比較廣泛,以萬兆計算,每秒傳輸大約 1250M 字節的數據,而 SATA 磁盤的讀寫速度這些年基本達到瓶頸,在 300-500M/s 附近,也就是純讀寫的話,網絡已經超過了磁盤的能力,再也不是瓶頸了,像 NAS 網絡磁盤這些年也開始普及起來。
但這並不表明,沒有必要對讀寫進行優化,畢竟網絡讀寫的速度仍是遠慢於內存的讀寫。常見的優化方法主要有:
緩存的使用在提升讀寫性能的同時,也會帶來數據不一致的問題:
這類問題有幾種方法:
因爲分佈式文件存儲系統,確定是一個多客戶端使用、多租戶的一個產品,而它又存儲了多是很重要的信息,因此安全性是它的重要部分。
主流文件系統的權限模型有如下這麼幾種:
Discretionary Access Control
,就是咱們熟悉的 Unix 類權限框架,以 user-group-privilege 爲三級體系,其中 user 就是 owner,group 包括 owner 所在 group 和非 owner 所在的 group、privilege 有 read、write 和 execute。這套體系主要是以 owner 爲出發點,owner 容許誰對哪些文件具備什麼樣的權限。Mandatory Access Control
,它是從資源的機密程度來劃分。好比分爲「普通」、「機密」、「絕密」這三層,每一個用戶可能對應不一樣的機密閱讀權限。這種權限體系起源於安全機構或軍隊的系統中,會比較常見。它的權限是由管理員來控制和設定的。Linux 中的 SELinux 就是 MAC 的一種實現,爲了彌補 DAC 的缺陷和安全風險而提供出來。關於 SELinux 所解決的問題能夠參考 What is SELinux?Role Based Access Control
,是基於角色 (role) 創建的權限體系。角色擁有什麼樣的資源權限,用戶歸到哪一個角色,這對應企業 / 公司的組織機構很是合適。RBAC 也能夠具體化,就演變成 DAC 或 MAC 的權限模型。市面上的分佈式文件系統有不一樣的選擇,像 ceph 就提供了相似 DAC 但又略有區別的權限體系,Hadoop 自身就是依賴於操做系統的權限框架,同時其生態圈內有 Apache Sentry 提供了基於 RBAC 的權限體系來作補充。
有連續空間和鏈表空間兩種。連續空間的優點是讀寫快,按順序便可,劣勢是形成磁盤碎片,更麻煩的是,隨着連續的大塊磁盤空間被分配滿而必須尋找空洞時,連續分配須要提早知道待寫入文件的大小,以便找到合適大小的空間,而待寫入文件的大小,每每又是沒法提早知道的 (好比可編輯的 word 文檔,它的內容能夠隨時增大);
而鏈表空間的優點是磁盤碎片不多,劣勢是讀寫很慢,尤爲是隨機讀,要從鏈表首個文件塊一個一個地往下找。
爲了解決這個問題,出現了索引表——把文件和數據塊的對應關係也保存一份,存在索引節點中 (通常稱爲 i 節點),操做系統會將 i 節點加載到內存,從而程序隨機尋找數據塊時,在內存中就能夠完成了。經過這種方式來解決磁盤鏈表的劣勢,若是索引節點的內容太大,致使內存沒法加載,還有可能造成多級索引結構。
實時刪除仍是延時刪除? 實時刪除的優點是能夠快速釋放磁盤空間;延時刪除只是在刪除動做執行的時候,置個標識位,後續在某個時間點再來批量刪除,它的優點是文件仍然能夠階段性地保留,最大程度地避免了誤刪除,缺點是磁盤空間仍然被佔着。在分佈式文件系統中,磁盤空間都是比較充裕的資源,所以幾乎都採用邏輯刪除,以對數據能夠進行恢復,同時在一段時間以後 (多是 2 天或 3 天,這參數通常均可配置),再對被刪除的資源進行回收。
怎麼回收被刪除或無用的數據? 能夠從文件的 meta 信息出發——若是 meta 信息的「文件 - 數據塊」映射表中包含了某個數據塊,則它就是有用的;若是不包含,則代表該數據塊已是無效的了。因此,刪除文件,實際上是刪除 meta 中的「文件 - 數據塊」映射信息 (若是要保留一段時間,則是把這映射信息移到另一個地方去)。
有不少這樣的場景,好比電商——那麼多的商品圖片、我的頭像,好比社交網站——那麼多的照片,它們具備的特性,能夠簡單概括下:
針對這種業務場景,主流的實現方式是仍然是以大數據塊的形式存儲,小文件以邏輯存儲的方式存在,即文件 meta 信息記錄其是在哪一個大數據塊上,以及在該數據塊上的 offset 和 length 是多少,造成一個邏輯上的獨立文件。這樣既複用了大數據塊系統的優點和技術積累,又減小了 meta 信息。
文件指紋就是根據文件內容,通過算法,計算出文件的惟一標識。若是兩個文件的指紋相同,則文件內容相同。在使用網絡雲盤的時候,發現有時候上傳文件很是地快,就是文件指紋發揮做用。雲盤服務商經過判斷該文件的指紋,發現以前已經有人上傳過了,則不須要真的上傳該文件,只要增長一個引用便可。在文件系統中,經過文件指紋能夠用來去重、也能夠用來判斷文件內容是否損壞、或者對比文件副本內容是否一致,是一個基礎組件。
文件指紋的算法也比較多,有熟悉的 md五、sha25六、也有 google 專門針對文本領域的 simhash 和 minhash 等。
分佈式文件系統內容龐雜,要考慮的問題遠不止上面所說的這些,其具體實現也更爲複雜。本文只是儘可能從分佈式文件系統所要考慮的問題出發,給予一個簡要的分析和設計,若是未來遇到相似的場景須要解決,能夠想到「有這種解決方案」,而後再來深刻研究。
同時,市面上也是存在多種分佈式文件系統的形態,下面就是有研究小組曾經對常見的幾種分佈式文件系統的設計比較。
從這裏也能夠看到,選擇其實不少,並非 GFS 論文中的方式就是最好的。在不一樣的業務場景中,也能夠有更多的選擇策略。