從RAID說起
大資料技術主要要解決的問題的是大規模資料的計算處理問題,那麼首先要解決的就是大規模資料的儲存問題。大規模資料儲存要解決的核心問題有三個方面:
資料儲存容量的問題,既然大資料要解決的是數以PB計的資料計算問題,而一般的伺服器磁碟容量通常1-2TB,那麼如何儲存這麼大規模的資料。
資料讀寫速度的問題,一般磁碟的連續讀寫速度為幾十MB,以這樣的速度,幾十PB的資料恐怕要讀寫到天荒地老。
資料可靠性的問題,磁碟大約是計算機裝置中最易損壞的硬體了,在網站一塊磁碟使用壽命大概是一年,如果磁碟損壞了,資料怎麼辦?
在大資料技術出現之前,人們就需要面對這些關於儲存的問題,對應的解決方案就是RAID技術。
RAID(獨立磁碟冗餘陣列)技術主要是為了改善磁碟的儲存容量,讀寫速度,增強磁碟的可用性和容錯能力。目前伺服器級別的計算機都支援插入多塊磁碟(8塊或者更多),通過使用RAID技術,實現資料在多塊磁碟上的併發讀寫和資料備份。
常用RAID技術有以下幾種,如圖所示。
假設伺服器有N塊磁碟。
RAID0
資料在從記憶體緩衝區寫入磁碟時,根據磁碟數量將資料分成N份,這些資料同時併發寫入N
塊磁碟,使得資料整體寫入速度是一塊磁碟的N倍。讀取的時候也一樣,因此RAID0具有極快的資料讀寫速度,但是RAID0不做資料備份,N塊磁碟中只要有一塊損壞,資料完整性就被破壞,所有磁碟的資料都會損壞。
RAID1
資料在寫入磁碟時,將一份資料同時寫入兩塊磁碟,這樣任何一塊磁碟損壞都不會導致資料丟失,插入一塊新磁碟就可以通過複製資料的方式自動修復,具有極高的可靠性。
RAID10
結合RAID0和RAID1兩種方案,將所有磁碟平均分成兩份,資料同時在兩份磁碟寫入,相當於RAID1,但是在每一份磁碟裡面的N/2塊磁碟上,利用RAID0技術併發讀寫,既提高可靠性又改善效能,不過RAID10的磁碟利用率較低,有一半的磁碟用來寫備份資料。
RAID3
一般情況下,一臺伺服器上不會出現同時損壞兩塊磁碟的情況,在只損壞一塊磁碟的情況下,如果能利用其他磁碟的資料恢復損壞磁碟的資料,這樣在保證可靠性和效能的同時,磁碟利用率也得到大幅提升。
在資料寫入磁碟的時候,將資料分成N-1份,併發寫入N-1塊磁碟,並在第N塊磁碟記錄校驗資料,任何一塊磁碟損壞(包括校驗資料磁碟),都可以利用其他N-1塊磁碟的資料修復。但是在資料修改較多的場景中,任何磁碟修改資料都會導致第N塊磁碟重寫校驗資料,頻繁寫入的後是第N塊磁碟比其他磁碟容易損壞,需要頻繁更換,所以RAID3很少在實踐中使用。
RAID5
相比RAID3,更多被使用的方案是RAID5。
RAID5和RAID3很相似,但是校驗資料不是寫入第
塊磁碟,而是螺旋式地寫入所有磁碟中。這樣校驗資料的修改也被平均到所有磁碟上,避免RAID3頻繁寫壞一塊磁碟的情況。
RAID6
如果資料需要很高的可靠性,在出現同時損壞兩塊磁碟的情況下(或者運維管理水平比較落後,壞了一塊磁碟但是遲遲沒有更換,導致又壞了一塊磁碟),仍然需要修復資料,這時候可以使用RAID6。
RAID6和RAID5類似,但是資料只寫入N-2塊磁碟,並螺旋式地在兩塊磁碟中寫入校驗資訊(使用不同演算法生成)。
在相同磁碟數目(N)的情況下,各種RAID技術的比較如下表所示。
RAID技術有硬體實現,比如專用的RAID卡或者主機板直接支援,也可以通過軟體實現,在作業系統層面將多塊磁碟組成RAID,在邏輯視作一個訪問目錄。RAID技術在傳統關聯式資料庫及檔案系統中應用比較廣泛,是改善計算機儲存特性的重要手段。
RAID技術只是在單臺伺服器的多塊磁碟上組成陣列,大資料需要更大規模的儲存空間和訪問速度。將RAID技術原理應用到分散式伺服器叢集上,就形成了Hadoop分散式檔案系統HDFS的架構思想。
HDFS架構原理
和RAID在多個磁碟上進行檔案儲存及並行讀寫一樣思路,HDFS在一個大規模分散式伺服器叢集上,對資料進行並行讀寫及冗餘儲存。因為HDFS可以部署在一個比較大的伺服器叢集上,叢集中所有伺服器的磁碟都可以供HDFS使用,所以整個HDFS的儲存空間可以達到PB級容量。HDFS架構如圖。
HDFS中關鍵元件有兩個,一個是NameNode,一個是DataNode。
DataNode負責檔案資料的儲存和讀寫操作,HDFS將檔案資料分割成若干塊(block),每個DataNode儲存一部分block,這樣檔案就分佈儲存在整個HDFS伺服器叢集中。應用程式客戶端(Client)可以並行對這些資料塊進行訪問,從而使得HDFS可以在伺服器叢集規模上實現資料並行訪問,極大地提高訪問速度。實踐中HDFS叢集的DataNode伺服器會有很多臺,一般在幾百臺到幾千臺這樣的規模,每臺伺服器配有數塊磁碟,整個叢集的儲存容量大概在幾PB到數百PB。
NameNode負責整個分散式檔案系統的後設資料(MetaData)管理,也就是檔案路徑名,資料block的ID以及儲存位置等資訊,承擔著作業系統中檔案分配表(FAT)的角色。HDFS為了保證資料的高可用,會將一個block複製為多份(預設情況為3份),並將三份相同的block儲存在不同的伺服器上。這樣當有磁碟損壞或者某個DataNode伺服器當機導致其儲存的block不能訪問的時候,Client會查詢其備份的block進行訪問。
block多份複製儲存如下圖所示,對於檔案/users/sameerp/data/part-0,其複製備份數設定為2,儲存的block id為1,3。block1的兩個備份儲存在DataNode0和DataNode2兩個伺服器上,block3的兩個備份儲存DataNode4和DataNode6兩個伺服器上,上述任何一臺伺服器當機後,每個block都至少還有一個備份存在,不會影響對檔案/users/sameerp/data/part-0的訪問。
事實上,DataNode會通過心跳和NameNode保持通訊,如果DataNode超時未傳送心跳,NameNode就會認為這個DataNode已經失效,立即查詢這個DataNode上儲存的block有哪些,以及這些block還儲存在哪些伺服器上,隨後通知這些伺服器再複製一份block到其他伺服器上,保證HDFS儲存的block備份數符合使用者設定的數目,即使再有伺服器當機,也不會丟失資料。
HDFS應用
Hadoop分散式檔案系統可以象一般的檔案系統那樣進行訪問:使用命令列或者程式語言API進行檔案讀寫操作。我們以HDFS寫檔案為例看HDFS處理過程,如下圖。
應用程式Client呼叫HDFS API,請求建立檔案,HDFS API包含在Client程式中。
HDFS API將請求引數傳送給NameNode伺服器,NameNode在meta資訊中建立檔案路徑,並查詢DataNode中空閒的block。然後將空閒block的id、對應的DataNode伺服器資訊返回給Client。因為資料塊需要多個備份,所以即使Client只需要一個block的資料量,NameNode也會返回多個NameNode資訊。
Client呼叫HDFS API,請求將資料流寫出。
HDFS API連線第一個DataNode伺服器,將Client資料流傳送給DataNode,該DataNode一邊將資料寫入本地磁碟,一邊傳送給第二個DataNode。同理第二個DataNode記錄資料併傳送給第三個DataNode。
Client通知NameNode檔案寫入完成,NameNode將檔案標記為正常,可以進行讀操作了。
HDFS雖然提供了API,但是在實踐中,我們很少自己程式設計直接去讀取HDFS中的資料,原因正如開篇提到,在大資料場景下,移動計算比移動資料更划算。於其寫程式去讀取分佈在這麼多DataNode上的資料,不如將程式分發到DataNode上去訪問其上的block資料。但是如何對程式進行分發?分發出去的程式又如何訪問HDFS上的資料?計算的結果如何處理,如果結果需要合併,該如何合併?
Hadoop提供了對儲存在HDFS上的大規模資料進行平行計算的框架,就是我們之前講的MapReduce。