從單機文件系統到分佈式文件系統

文件及硬盤管理是計算機操作系統的重要組成部分,文件是存儲在硬盤上的,文件的讀寫訪問速度必然受到硬盤的物理限制,那麼如何才能1分鐘完成一個100T大文件的遍歷呢?

做軟件開發時,必然要經常和文件系統打交道,而文件系統也是一個軟件,瞭解文件系統的設計原理,可以幫助我們更好地使用文件系統,另外設計文件系統時的各種考量,也對我們自己做軟件設計有諸多借鑑意義。

硬盤

硬盤是一種可持久保存、多次讀寫數據的存儲介質。硬盤的形式主要兩種,一種是機械式硬盤,一種是固態硬盤。

機械式硬盤的結構,主要包含盤片、主軸、磁頭臂,主軸帶動盤片高速旋轉,當需要讀寫盤上的數據的時候,磁頭臂會移動磁頭到盤片所在的磁道上,磁頭讀取磁道上的數據。讀寫數據需要移動磁頭,這樣一個機械的動作,至少需要花費數毫秒的時間,這是機械式硬盤訪問延遲的主要原因。

如果一個文件的數據在硬盤上不是連續存儲的,比如數據庫的B+樹文件,那麼要讀取這個文件,磁頭臂就必須來回移動,花費的時間必然很長。如果文件數據是連續存儲的,比如日誌文件,那麼磁頭臂就可以較少移動,相比離散存儲的同樣大小的文件,連續存儲的文件的讀寫速度要快得多。

機械式硬盤的數據就存儲在具有磁性特質的盤片上,因此這種硬盤也被稱爲磁盤,而固態硬盤則沒有這種磁性特質的存儲介質,也沒有電機驅動的機械式結構。其中主控芯片處理端口輸入的指令和數據,然後控制閃存顆粒進行數據讀寫。由於固態硬盤沒有了機械式硬盤的電機驅動磁頭臂進行機械式物理移動的環節,而是完全的電子操作,因此固態硬盤的訪問速度遠快於機械式硬盤。

但是,到目前爲止固態硬盤的成本還是明顯高於機械式硬盤,因此在生產環境中,最主要的存儲介質依然是機械式硬盤。如果一個場景對數據訪問速度、存儲容量、成本都有較高要求,那麼可以採用固態硬盤和機械式硬盤混合部署的方式,即在一臺服務器上既有固態硬盤,也有機械式硬盤,以滿足不同文件類型的存儲需求,比如日誌文件存儲在機械式硬盤上,而系統文件和隨機讀寫的文件存儲在固態硬盤上。

文件系統

作爲應用程序開發者,我們不需要直接操作硬盤,而是通過操作系統,以文件的方式對硬盤上的數據進行讀寫訪問。文件系統將硬盤空間以塊爲單位進行劃分,每個文件佔據若干個塊,然後再通過一個文件控制塊FCB(File Controll Block)記錄每個文件佔據的硬盤數據塊

在這裏插入圖片描述

這個文件控制塊在Linux操作系統中就是inode,要想訪問文件,就必須獲得文件的inode 信息,在inode中查找文件數據塊索引表,根據索引中記錄的硬盤地址信息訪問硬盤,讀寫數據。

inode中記錄着文件權限、所有者、修改時間和文件大小等文件屬性信息,以及文件數據塊硬盤地址索引。inode是固定結構的,能夠記錄的硬盤地址索引數也是固定的,只有15個索引。其中前12個索引直接記錄數據塊地址,第13個索引記錄索引地址,也就是說,索引塊指向的硬盤數據塊並不直接記錄文件數據,而是記錄文件數據塊的索引表,每個索引表可以記錄 256個索引;第14個索引記錄二級索引地址,第15個索引記錄三級索引地址,如下圖:

在這裏插入圖片描述

這樣,每個 inode 最多可以存儲12+256+256256+256256*256個數據塊,如果每個數據塊的大小爲4k,也就是單個文件最大不超過70G,而且即使可以擴大數據塊大小,文件大小也要受單個硬盤容量的限制。

這樣的話,對於我們存儲並快速遍歷一份100TB的大文件,Linux文件系統是無法完成的。那麼有沒有更給力的解決方案呢?

獨立硬盤冗餘陣列(RAID)

RAID( Redundant Array of Independent Disks),即獨立硬盤冗餘陣列,將多塊硬盤通過硬件RAID卡或者軟件RAID的方案管理起來,使其共同對外提供服務,目標是提升性能或數據冗餘,或者兩者同時提升。RAID的核心思路其實是利用文件系統將數據寫入硬盤中不同數據塊的特性,將多塊硬盤上的空閒空間看做一個整體,進行數據寫入,也就是說,一個文件的多個數據塊可能寫入多個硬盤

在運作中,取決於RAID層級不同,數據會以多種模式分散於各個硬盤,RAID層級的命名會以RAID開頭並帶數字。常用 RAID有五種,分別是 RAID 0、RAID 1、RAID 10、RAID 5和RAID 6。每種等級都有其理論上的優缺點,不同的等級在兩個目標間獲取平衡,分別是增加數據可靠性以及增加存儲器(羣)讀寫性能。

在這裏插入圖片描述

RAID 0將一個文件的數據分成N片,同時向N個硬盤寫入,這樣單個文件可以存儲在N個硬盤上,文件容量可以擴大N倍,(理論上)讀寫速度也可以擴大N倍。但是使用 RAID 0的最大問題是文件數據分散在N塊硬盤上,任何一塊硬盤損壞,就會導致數據不完整,整個文件系統全部損壞,文件的可用性極大地降低了,RAID 0既沒有冗餘功能,也不具備容錯能力。

RAID 1則是利用兩塊硬盤進行數據備份,文件同時向兩塊硬盤寫入,這樣任何一塊硬盤損壞都不會出現文件數據丟失的情況,文件的可用性得到提升。其原理爲在主硬盤上存放數據的同時也在鏡像硬盤上寫一樣的數據。當主硬盤(物理)損壞時,鏡像硬盤則代替主硬盤的工作。因爲有鏡像硬盤做數據備份,所以RAID 1的數據安全性在所有的RAID級別上來說是最好的。但無論用多少磁盤做RAID 1,僅算一個磁盤的容量,是所有RAID中磁盤利用率最低的一個級別。

RAID 10結合RAID 0和RAID 1,將多塊硬盤進行兩兩分組,文件數據分成 N片,每個分組寫入一片,每個分組內的兩塊硬盤再進行數據備份。這樣既擴大了文件的容量,又提高了文件的可用性。但是這種方式硬盤的利用率只有50%,有一半的硬盤被用來做數據備份。

RAID 5針對RAID 10硬盤浪費的情況,是一種儲存性能、數據安全和存儲成本兼顧的存儲解決方案。將數據分成N-1片,再利用這N-1片數據進行位運算,計算出1片校驗數據,然後將這N片數據寫入N個硬盤。RAID 5至少需要三個硬盤,RAID 5不是對存儲的數據進行備份,而是把數據和相對應的校驗信息存儲到組成RAID 5的各個磁盤上,並且校驗信息和相對應的數據分別存儲於不同的磁盤上。這樣任何一塊硬盤損壞,都可以利用剩下的數據和相應的奇偶校驗信息去恢復被損壞的數據,而硬盤的利用率也提高到N-1/N

RAID 5可以解決一塊硬盤損壞後文件不可用的問題,那麼如果兩塊文件損壞?RAID 6的解決方案是,用兩種位運算校驗算法計算2片校驗數據,這樣兩塊硬盤損壞還是可以計算得到丟失的數據片。

實踐中,使用最多的是RAID 5,數據被分成N-1片併發寫入N-1塊硬盤,這樣既可以得到較好的硬盤利用率,也能得到很好的讀寫速度,同時還能保證較好的數據可用性。使用RAID 5的文件系統比簡單的文件系統文件容量和讀寫速度都提高了N-1倍,但是一臺服務器上能插入的硬盤數量是有限的,通常是8塊,也就是文件讀寫速度和存儲容量提高了7倍,這遠遠達不到1分鐘完成100T文件的遍歷要求

需要更給力的解決方案。

分佈式文件系統

再回過頭看下Linux的文件系統:文件的基本信息,也就是文件元信息記錄在文件控制塊inode中,文件的數據記錄在硬盤的數據塊中,inode通過索引記錄數據塊的地址,讀寫文件的時候,查詢inode中的索引記錄得到數據塊的硬盤地址,然後訪問數據。如果將數據塊的地址改成分佈式服務器的地址呢?也就是查詢得到的數據塊地址不只是本機的硬盤地址,還可以是其他服務器的地址,那麼文件的存儲容量就將是整個分佈式服務器集羣的硬盤容量,這樣還可以在不同的服務器上同時並行讀取文件的數據塊,文件訪問速度也將極大的加快。

這樣的文件系統就是分佈式文件系統,分佈式文件系統的思路其實和RAID 是一脈相承的,就是將數據分成很多片,同時向N臺服務器上進行數據寫入。針對一片數據丟失就導致整個文件損壞的情況,分佈式文件系統也是採用數據備份的方式,將多個備份數據片寫入多個服務器,以保證文件的可用性。當然,也可以採用RAID 5的方式通過計算校驗數據片的方式提高文件可用性。

以Hadoop分佈式文件系統HDFS爲例,看下分佈式文件系統的具體架構設計。

在這裏插入圖片描述

HDFS的關鍵組件有兩個,一個是DataNode,一個是NameNode。

DataNode負責文件數據的存儲和讀寫操作,HDFS將文件數據分割成若干數據塊(Block),每個DataNode存儲一部分數據塊,這樣文件就分佈存儲在整個HDFS服務器集羣中。應用程序客戶端(Client)可以並行對這些數據塊進行訪問,從而使得HDFS可以在服務器集羣規模上實現數據並行訪問,極大地提高了訪問速度。在實踐中,HDFS集羣的DataNode服務器會有很多臺,一般在幾百臺到幾千臺這樣的規模,每臺服務器配有數塊硬盤,整個集羣的存儲容量大概在幾PB到數百PB。

NameNode負責整個分佈式文件系統的元數據(MetaData)管理,也就是文件路徑名、訪問權限、數據塊的ID以及存儲位置等信息,相當於Linux系統中inode的角色,要以使用主從的容災方式(一主一備,互爲熱備)。HDFS爲了保證數據的高可用,會將一個數據塊複製爲多份(缺省情況爲3份),並將多份相同的數據塊存儲在不同的服務器上,甚至不同的機架上。這樣當有硬盤損壞,或者某個DataNode服務器宕機,甚至某個交換機宕機,導致其存儲的數據塊不能訪問的時候,客戶端會查找其備份的數據塊進行訪問

有了HDFS,可以實現單一文件存儲幾百T的數據,再配合大數據計算框架MapReduce或者Spark,可以對這個文件的數據塊進行併發計算。也可以使用Impala這樣的SQL引擎對這個文件進行結構化查詢,在數千臺服務器上併發遍歷100T的數據,1分鐘都是綽綽有餘的。

小結

文件系統從簡單操作系統文件,到RAID,再到分佈式文件系統,其設計思路其實是具有統一性的。這種統一性一方面體現在文件數據如何管理,也就是如何通過文件控制塊管理文件的數據,這個文件控制塊在Linux系統中就是inode,在HDFS中就是NameNode。另一方面體現在如何利用更多的硬盤實現越來越大的文件存儲需求和越來越快的讀寫速度需求,也就是將數據分片後同時寫入多塊硬盤。

單服務器我們可以通過RAID來實現,多服務器則可以將這些服務器組成一個文件系統集羣,共同對外提供文件服務,這時候,數千臺服務器的數萬塊硬盤以單一存儲資源的方式對文件使用者提供服務,也就是一個文件可以存儲數百T的數據,並在一分鐘完成這樣一個大文件的遍歷。

HDFS與HBase

HDFS是Hadoop分佈式文件系統。而HBase的數據通常存儲在HDFS上。HDFS爲HBase提供了高可靠性的底層存儲支持。Hbase是Hadoop database即Hadoop數據庫。它是一個適合於非結構化數據存儲的數據庫,HBase基於列的而不是基於行的模式。HBase是Google Bigtable的開源實現,類似Google Bigtable利用GFS作爲其文件存儲系統,HBase利用Hadoop HDFS作爲其文件存儲系統;Google運行MapReduce來處理Bigtable中的海量數據,HBase同樣利用Hadoop MapReduce來處理HDFS中的海量數據。

HDFS爲HBase提供了高可靠性的底層存儲支持,Hadoop MapReduce爲HBase提供了高性能的計算能力,Zookeepper提供一個分佈式的無中心的元數據存儲服務Zookeeper,爲HBase提供了服務器狀態探測和failover機制。Pig和Hive還爲HBase提供了高層語言支持,使得在HBase上進行數據統計處理變的非常簡單。 Sqoop則爲HBase提供了方便的RDBMS(關係型數據庫)數據導入功能,使得傳統關係型數據庫的數據向HBase中遷移變的非常方便。

HBase本身其實可以完全不要考慮HDFS的,你完全可以只把HBase當作是一個分佈式高併發k-v存儲系統,只不過它底層的文件系統是通過HDFS來支持的罷了。換做其他的分佈式文件系統也是一樣的,不影響HBase的本質。甚至如果你不考慮文件系統的分佈式或穩定性等特性的話,完全可以用簡單的本地文件系統,甚至內存文件系統來代替。

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