HDFS架構(gòu)剖析

1.背景

HDFS最初是參考谷歌GFS論文原理開發(fā)的一個開源產(chǎn)品疗我,由Lucene開源項目的創(chuàng)始人Doug Cutting開發(fā)眠菇,現(xiàn)在已經(jīng)成為大數(shù)據(jù)平臺的基石忆植。HDFS借鑒了GFS的技術(shù)架構(gòu)挡鞍,在設(shè)計理念上又與GFS有很大的不同,它致力于提供一個通用的分布式文件系統(tǒng)历葛,與GFS作為Google內(nèi)部存儲系統(tǒng)的定位有很大區(qū)別。

HDFS定義了一套文件系統(tǒng)API規(guī)范(http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/filesystem/index.html)嘀略,確立了HDFS的核心模型恤溶,為用戶提供了一個穩(wěn)定的依賴乓诽。

HDFS的核心模型:

  • 名稱

HDFS文件、目錄的命名規(guī)則咒程,及其邏輯關(guān)系问裕,與Linux普通文件系統(tǒng)看起來幾乎一模一樣。

  • 原子性

在HDFS中孵坚,創(chuàng)建文件粮宛、刪除文件、重命名文件卖宠、重命名目錄巍杈、創(chuàng)建目錄都是原子操作。遞歸刪除目錄也是原子操作扛伍。

  • 一致性

HDFS的一致性模型是”復(fù)制-更新“語義筷畦,我理解就是是強一致模型。

Create刺洒、Update鳖宾、Delete、Delete then create逆航、Rename操作鼎文,在操作結(jié)束后,結(jié)果必須對后續(xù)的訪問可見因俐。

  • 并發(fā)

HDFS對并發(fā)操作沒有數(shù)據(jù)隔離保證拇惋。假如一個Client在訪問文件的同時,另一個Client正在修改文件抹剩,那么修改的內(nèi)容可能可見撑帖,也可能不可見。

  • 操作失敗

所有操作必須最終完成澳眷,要么成功胡嘿,要么失敗。

實現(xiàn)通過重試來保證操作成功钳踊,前提是保證一致性語義衷敌,并且重試操作對Client透明。

  • 超時

HDFS對操作的超時沒有定義箍土。

在HDFS中逢享,阻塞操作超時實際上是可變的,因為站點和客戶機可能會調(diào)優(yōu)重試參數(shù)吴藻,從而將文件系統(tǒng)故障和故障排除程序轉(zhuǎn)換為操作中的暫停瞒爬。取而代之的是一種普遍的假設(shè),即FS操作“快但沒有本地FS操作快”,并且數(shù)據(jù)讀寫的延遲隨數(shù)據(jù)量的增加而增加侧但∈缚眨客戶機應(yīng)用程序的這種假設(shè)揭示了一個更基本的假設(shè):文件系統(tǒng)性能接近網(wǎng)絡(luò)延遲和帶寬上線。

對于某些操作的開銷也有一些隱含的假設(shè)禀横。seek()操作非称ㄒ快,幾乎不會造成網(wǎng)絡(luò)延遲柏锄。對于條目較少的目錄酿箭,目錄列表操作非常快趾娃。

  • vs 對象存儲

HDFS與對象存儲(例如S3)有明顯的不同缭嫡,

  • 對象存儲是最終一致性模型。也就是說抬闷,一個操作的結(jié)果妇蛀,要經(jīng)過一段時間才能被所有的Client看到,在此之前笤成,Client可能訪問到過期數(shù)據(jù)评架。

  • 原子性。對象存儲沒有目錄的概念炕泳,雖然可以通過基于文件名前綴的操作纵诞,來達到類似的效果,比如通過刪除前綴/user的文件喊崖,來達到刪除/user目錄的效果挣磨,但這不是一個原子操作,而是一個文件一個文件的獨立操作荤懂。

  • 持久性。HDFS和傳統(tǒng)文件持久化非常相近塘砸,調(diào)用flush节仿,close,文件以流的形式不停得更新到存儲掉蔬。而對象存儲只有對文件操作結(jié)束后的時刻廊宪,才把完整的文件PUT到存儲系統(tǒng)。

  • 權(quán)限女轿。HDFS提供傳統(tǒng)文件系統(tǒng)的用戶箭启、組權(quán)限管理概念,對象存儲通常沒有蛉迹。

2.架構(gòu)

HDFS架構(gòu)和GFS非常相近傅寡,可以參考上一篇筆記《GFS架構(gòu)剖析》,這里只說一下二者的區(qū)別。

2.1 Moving Computation is Cheaper than Moving Data

這是HDFS的一個設(shè)計預(yù)期和目標荐操,也是Hadoop大數(shù)據(jù)處理的精髓所在芜抒。

2.2 The File System Namespace

HDFS目標是做一個通用文件系統(tǒng),支持傳統(tǒng)的文件托启、目錄概念宅倒。在這方面,GFS更像一個對象存儲屯耸,它不支持文件系統(tǒng)模型拐迁。

2.3 BlockId

根據(jù)[1],早期block id是一個64位數(shù)隨機數(shù)疗绣。當時實現(xiàn)比較簡單线召,并沒有判重,所以如果兩個block碰巧得到同樣的block id持痰,系統(tǒng)會誤認為是多余的備份block灶搜,而將其中一個刪除。這樣這個block很有可能會出錯工窍,包含它的文件則損壞割卖。解決的辦法有兩個,一是記錄好所有使用過的block id患雏,以實現(xiàn)判重功能鹏溯;二是以一種不會重復(fù)的方式生成block id,比如順序生成淹仑。順序生成的缺點有三個丙挽,一是現(xiàn)有的系統(tǒng)遷移困難,所有的block都要重新命名匀借;二是用完了64位數(shù)后仍然有麻煩颜阐;三是要記錄好最高的block id。

判重并不是最優(yōu)的方法吓肋,因為它需要額外的工作凳怨,而且隨著文件系統(tǒng)變得龐大將變重。假設(shè)用一個Hash實現(xiàn)判重是鬼,一個1PB的文件系統(tǒng),假設(shè)1個block大小64MB,則包含有16M個block id囤耳,每個id為8個byte,則需要一個128MB的Hash表撒桨,這對于一個本身就很復(fù)雜的NameNode是個不小的壓力。[2]中提出了一種綜合的方法夷磕,給一個文件的所有block指定一個相同的range id(5個byte)作為它們block id的高位膘螟,然后按順序每個block生成剩余的3個byte。較之前的單純判重埋合,好處在于減小了判重的數(shù)量蹭睡;同時又方便管理同一個文件的block辫呻,因為它們的block id是連續(xù)的清钥。[2]也指出這種方法的問題,當一個文件被刪除時放闺,此range id要從系統(tǒng)中抹去祟昭,如果此時某個包含此文件某block的數(shù)據(jù)結(jié)點掉線了,在它重新上線之后怖侦,它又帶回這個已經(jīng)無效的range id篡悟。所以需要timestamps,即creation time of the file匾寝,當兩個文件碰巧有相同的range id時搬葬,根據(jù)timestamps來判定誰是最新的文件,舊的文件將被刪除旗吁。[2]中能看到Doug Cutting和Sameer Paranjpye的一些其它討論踩萎,比如range-id也采用順序生成(又回到隨機VS順序的問題上)。

[1] potential conflict in block id's, leading to data corruption

https://issues.apache.org/jira/browse/HADOOP-146

[2] dfs should allocate a random blockid range to a file, then assign ids sequentially to blocks in the file

https://issues.apache.org/jira/browse/HADOOP-158

[3] Sequential generation of block ids

https://issues.apache.org/jira/browse/HDFS-898

2.4 數(shù)據(jù)校驗

硬盤故障很钓、網(wǎng)絡(luò)錯誤或軟件漏洞香府,都可能造成數(shù)據(jù)損壞÷刖耄客戶端創(chuàng)建文件時企孩,會針對文件的每一個Block計算校驗碼,并把校驗碼存儲在相同命名空間一個單獨的因此文件中袁稽。當客戶端讀數(shù)據(jù)時勿璃,會使用這些校驗碼進行數(shù)據(jù)驗證。如果校驗失敗推汽,客戶端會從其他副本重新拉取文件补疑。

這一點上HDFS與GFS差異明顯。GFS數(shù)據(jù)校驗是在chunkserver上做的歹撒,并且是對每一個64K的塊計算一個校驗碼莲组,應(yīng)用程序也需要構(gòu)建自己的記錄校驗碼,因為GFS文件可能中可能存在填充數(shù)據(jù)暖夭、重復(fù)數(shù)據(jù)锹杈。而HDFS是強一致模型撵孤,各副本在字節(jié)上完全一致,所以客戶端可以直接使用每一個Block的校驗碼進行數(shù)據(jù)校驗竭望。

2.5 元數(shù)據(jù)備份與恢復(fù)

2.5.1 Secondary NameNode

Secondary NameNode不是NameNode的備份邪码。它的作用是:定期合并fsImage和editsLog,并推送給NameNode咬清,輔助恢復(fù)NameNode(editsLog越大NameNode恢復(fù)越慢)闭专。

Secondary NameNode的作用現(xiàn)在可以被CheckpointNode和BackupNode替換掉。

Secondary NameNode定期合并流程枫振,如下圖所示喻圃。

image

2.5.2 Checkpoint Node

CheckpointNode和SecondaryNameNode的作用以及配置完全相同。

2.5.3 Backup Node

Backup Node在內(nèi)存中維護了一份從Namenode同步過來的fsimage粪滤,同時它還從namenode接收edits文件的日志流斧拍,并把它們持久化硬盤,Backup Node把收到的這些edits文件和內(nèi)存中的fsimage文件進行合并杖小,創(chuàng)建一份元數(shù)據(jù)備份肆汹。Backup Node高效的秘密就在這兒,它不需要從Namenode下載fsimage和edit予权,把內(nèi)存中的元數(shù)據(jù)持久化到磁盤然后進行合并即可昂勉。

配置了BackupNode以后,NameNode自身不再需要持久化存儲扫腺,而是把這個職責(zé)完全委托給BackupNode岗照。

目前,hadoop集群只支持一個Backup Node笆环,如果Backup Node出了問題攒至,Hadoop元數(shù)據(jù)的備份機制也就失效了,所以hadoop計劃在未來能支持多個Backup Node躁劣。

2.5.4 Recovery Mode

當所有的元數(shù)據(jù)備份都失效時迫吐,可以啟動Recovery模式,來恢復(fù)大部分數(shù)據(jù)账忘。

2.6 NameNode HA

image

NameNode的HA志膀,指的是在一個集群中存在兩個NameNode,分別運行在獨立的物理節(jié)點上鳖擒。在任何時間點溉浙, 只有一個NameNodes是處于Active狀態(tài),另一種是在Standby狀態(tài)蒋荚。

Active NameNode負責(zé)所有的客戶端的操作放航,而Standby NameNode用來同步Active NameNode的狀態(tài)信息,以提供快速的故障恢復(fù)能力圆裕。

為了保證Active NameNode與Standby NameNode節(jié)點狀態(tài)同步广鳍,即元數(shù)據(jù)保持一致。除了DataNode需要向兩個NN發(fā)送block位置信息外吓妆,還構(gòu)建了一組獨立的守護進程”JournalNodes” 赊时,用來同步FsEdits信息。當Active NameNode執(zhí)行任何有關(guān)命名空間的修改行拢,它需要持久化到一半以上的JournalNodes上祖秒。而Standby NameNode負責(zé)觀察JNs的變化,讀取從Active NameNode發(fā)送過來的FsEdits信息舟奠,并更新其內(nèi)部的命名空間竭缝。

一旦Active NameNode遇到錯誤, Standby NameNode需要保證從JNs中讀出了全部的FsEdits沼瘫, 然后切換成Active狀態(tài)抬纸。

在這個圖里,我們可以看出HA的大致架構(gòu)耿戚,其設(shè)計上的考慮包括:

  • 利用共享存儲來在兩個NN間同步edits信息湿故。

共享存儲有兩個方案,一是通過NFS膜蛔,在中高端的存儲設(shè)備內(nèi)部都有各種RAID以及冗余硬件包括電源以及網(wǎng)卡等坛猪,比服務(wù)器的可靠性還是略有提高。二是通過QJM集群皂股,QJM集群有一個特性墅茉,數(shù)據(jù)寫入只有被集群的大多數(shù)節(jié)點接受,才算寫入成功呜呐,這也就保證任何時刻就斤,只有一個NameNode可以寫入數(shù)據(jù)。

  • DataNode同時向兩個NameNode匯報塊信息卵史。

這是讓Standby NameNode保持集群最新狀態(tài)的必需步驟战转。

  • 用于監(jiān)視和控制NN進程的FailoverController進程

顯然,我們不能在NameNode進程內(nèi)進行心跳等信息同步以躯。最簡單的原因槐秧,一次FullGC就可以讓NameNode掛起十幾分鐘。所以忧设,必須要有一個獨立的短小精悍的watchdog來專門負責(zé)監(jiān)控刁标。這也是一個松耦合的設(shè)計,便于擴展或更改址晕,目前版本里是用ZooKeeper(以下簡稱ZK)來做同步鎖膀懈,但用戶可以方便的把這個ZooKeeper FailoverController(以下簡稱ZKFC)替換為其他的HA方案或leader選舉方案。

  • 隔離(Fencing)谨垃,防止腦裂启搂,就是保證在任何時候只有一個主NameNode硼控,包括三個方面:

共享存儲fencing,確保只有一個NameNode可以寫入edits胳赌。

客戶端fencing牢撼,確保只有一個NameNode可以響應(yīng)客戶端的請求。

DataNode fencing疑苫,確保只有一個NameNode可以向DateNode下發(fā)命令熏版,譬如刪除,復(fù)制等等捍掺。

2.7 Multiple NameNodes/Namespaces

image

HDFS提供了一種水平擴展方案撼短,即通過NameNode集群+共享DateNode的方式,支持多個獨立的命名空間挺勿。

DateNode向集群的所有NameNode注冊曲横,周期性發(fā)送心跳,發(fā)送BlockReport满钟。NameNode之間彼此不通信胜榔。

每一個NameNode維護自己的BlockPools,BlockPools在DataNode上被單獨管理湃番。因此夭织,NameNode節(jié)點之間不需要任何同步,可以單獨生成Block IDs吠撮。當一個NameNode發(fā)生故障時尊惰,不影響DateNode向其他的NameNode正常提供服務(wù)。

命名空間和它的BlockPool一起構(gòu)成一個“卷”泥兰,它是一個獨立管理的單位弄屡,當一個"卷"被刪除時,BlockPool對應(yīng)的Block也會被DateNode節(jié)點刪除鞋诗。在集群升級期間膀捷,每個命名空間卷作為一個單元進行升級。

這種方案帶來的好處:

  • 命名空間可擴展性:在使用小文件的場景中削彬,可以從擴展多個命名空間獲益全庸。
  • 性能:使性能不再局限于一個NameNode節(jié)點。
  • 隔離:通過命名空間避免不同的應(yīng)用融痛,避免互相影響蛾方。

為了讓多個命名空間對Client看起來還像是一個集群冠绢,可以使用ViewFs脏榆。這就像是Linux文件系統(tǒng)的掛載表缘厢,每個文件系統(tǒng)掛載在一個目錄上,使用起來,看到的是一個命名空間责语,不必關(guān)心具體是由幾個文件系統(tǒng)構(gòu)成的炮障。

image

為了給Client提供一個統(tǒng)一視圖,HDFS提供了一個Router方案鹦筹,即通過Router代理Client對NameNode的請求铝阐,使多集群對Client透明。

image

最簡單的配置是在每個NameNode機器上部署Router铐拐。當ClientS訪問文件系統(tǒng)中的文件時,路由器檢查StateStore找出哪個子集群包含該文件, 然后代理請求到相應(yīng)的NameNode练对。

2.8 配額

HDFS支持對一個目錄下的子目錄和文件數(shù)進行限額遍蟋,對一個目錄的存儲空間限額,對一個目錄在不同存儲介質(zhì)上的存儲空間(DISK/SSD/ARCHIVE)螟凭。限額數(shù)據(jù)在NameNode被持久化保存虚青。

2.9 訪問接口

HDFS支持眾多訪問接口,包括:

  • Shell
  • 標準Java API
  • HFTP
  • C API libhdfs
  • RestApi
  • NFS GateWay

2.10 集中的緩存管理

HDFS提供了一種集中式緩存管理機制螺男,允許用戶指定HDFS緩存的路徑棒厘。NameNode與存儲相應(yīng)下文件的DateNode進行通信,指示它們將塊緩存到堆外緩存中下隧。

2.10.1 主要解決了哪些問題

  • 用戶可以根據(jù)自己的邏輯指定一些經(jīng)常被使用的數(shù)據(jù)或者高優(yōu)先級任務(wù)對應(yīng)的數(shù)據(jù)常駐內(nèi)存而不被淘汰到磁盤奢人。例如在Hive或Impala構(gòu)建的數(shù)據(jù)倉庫應(yīng)用中fact表會頻繁地與其他表做JOIN,顯然應(yīng)該讓fact常駐內(nèi)存淆院,這樣DataNode在內(nèi)存使用緊張的時候也不會把這些數(shù)據(jù)淘汰出去何乎,同時也實現(xiàn)了對于 mixed workloads的SLA。

  • centralized cache是由NameNode統(tǒng)一管理的土辩,那么HDFS client(例如MapReduce支救、Impala)就可以根據(jù)block被cache的分布情況去調(diào)度任務(wù),做到memory-locality拷淘。

  • HDFS原來單純靠DataNode的OS buffer cache各墨,這樣不但沒有把block被cache的分布情況對外暴露給上層應(yīng)用優(yōu)化任務(wù)調(diào)度,也有可能會造成cache浪費启涯。例如一個block的三個replica分別存儲在三個DataNote 上贬堵,有可能這個block同時被這三臺DataNode的OS buffer cache,那么從HDFS的全局看就有同一個block在cache中存了三份逝嚎,造成了資源浪費扁瓢。

  • 加快HDFS client讀速度。過去NameNode處理讀請求時只根據(jù)拓撲遠近決定去哪個DataNode讀补君,現(xiàn)在還要加入speed的因素引几。當HDFS client和要讀取的block被cache在同一臺DataNode的時候,可以通過zero-copy read直接從內(nèi)存讀,略過磁盤I/O伟桅、checksum校驗等環(huán)節(jié)敞掘。

image

2.10.2 架構(gòu)和原理

用戶可以通過hdfs cacheadmin命令行或者HDFS API顯式指定把HDFS上的某個文件或者目錄放到HDFS centralized cache中。這個centralized cache由分布在每個DataNode節(jié)點的off-heap內(nèi)存組成楣铁,同時被NameNode統(tǒng)一管理玖雁。每個DataNode節(jié)點使用mmap/mlock把存儲在磁盤文件中的HDFS block映射并鎖定到off-heap內(nèi)存中。

Client讀取文件時向NameNode發(fā)送getBlockLocations RPC請求盖腕。NameNode會返回一個LocatedBlock列表給Client赫冬,這個LocatedBlock對象里有這個block的replica所在的DataNode和cache了這個block的DataNode±A校可以理解為把被cache到內(nèi)存中的replica當做三副本外的一個高速的replica劲厌。

2.10.3 對應(yīng)用的影響

對于HDFS上的某個目錄已經(jīng)被addDirective緩存起來之后,如果這個目錄里新加入了文件听隐,那么新加入的文件也會被自動緩存补鼻。這一點對于Hive/Impala式的應(yīng)用非常有用。

HBase in-memory table:可以直接把某個HBase表的HFile放到centralized cache中雅任,這會顯著提高HBase的讀性能风范,降低讀請求延遲。

和Spark RDD的區(qū)別:多個RDD的之間的讀寫操作可能完全在內(nèi)存中完成沪么,出錯就重算硼婿。HDFS centralized cache中被cache的block一定是先寫到磁盤上的,然后才能顯式被cache到內(nèi)存成玫。也就是說只能cache讀加酵,不能cache寫。

目前的centralized cache不是DFSClient讀了誰就會把誰cache哭当,而是需要DFSClient顯式指定要cache誰猪腕,cache多長時間,淘汰誰钦勘。目前也沒有類似LRU的置換策略陋葡,如果內(nèi)存不夠用的時候需要client顯式去淘汰對應(yīng)的directive到磁盤。

現(xiàn)在還沒有跟YARN整合彻采,需要用戶自己調(diào)整留給DataNode用于cache的內(nèi)存和NodeManager的內(nèi)存使用腐缤。

2.11 HDFS讀寫流程

2.11.1 HDFS中的block、packet肛响、chunk

要把讀寫過程細節(jié)搞明白前岭粤,必須知道block、packet與chunk特笋。

  • block

這個大家應(yīng)該知道剃浇,文件上傳前需要分塊,這個塊就是block,一般為128MB虎囚,當然你可以去改角塑,不過不推薦。因為塊太刑约ァ:尋址時間占比過高圃伶。塊太大:Map任務(wù)數(shù)太少,作業(yè)執(zhí)行速度變慢蒲列。它是最大的一個單位窒朋。

  • packet

packet是第二大的單位,它是client端向DataNode蝗岖,或DataNode的PipLine之間傳數(shù)據(jù)的基本單位炼邀,默認64KB。

  • chunk

chunk是最小的單位剪侮,它是client向DataNode,或DataNode的PipLine之間進行數(shù)據(jù)校驗的基本單位洛退,默認512Byte瓣俯,因為用作校驗,故每個chunk需要帶有4Byte的校驗位兵怯。所以實際每個chunk寫入packet的大小為516Byte彩匕。由此可見真實數(shù)據(jù)與校驗值數(shù)據(jù)的比值約為128 : 1。(即64*1024 / 512)

例如媒区,在client端向DataNode傳數(shù)據(jù)的時候驼仪,HDFSOutputStream會有一個chunk buff,寫滿一個chunk后袜漩,會計算校驗和并寫入當前的chunk(追加操作如何計算chunk的校驗碼绪爸?)。之后再把帶有校驗和的chunk寫入packet宙攻,當一個packet寫滿后奠货,packet會進入dataQueue隊列,其他的DataNode就是從這個dataQueue獲取client端上傳的數(shù)據(jù)并存儲的座掘。同時一個DataNode成功存儲一個packet后之后會返回一個ack packet递惋,放入ack Queue中。

2.11.2 讀流程

image

HDFS的讀主要有三種: 網(wǎng)絡(luò)I/O讀 -> short circuit read -> zero-copy read溢陪。網(wǎng)絡(luò)I/O讀就是傳統(tǒng)的HDFS讀萍虽,通過DFSClient和Block所在的DataNode建立網(wǎng)絡(luò)連接傳輸數(shù)據(jù)。

當DFSClient和它要讀取的block在同一臺DataNode時形真,DFSClient可以跨過網(wǎng)絡(luò)I/O直接從本地磁盤讀取數(shù)據(jù)杉编,這種讀取數(shù)據(jù)的方式叫short circuit read。

目前HDFS實現(xiàn)的short circuit read是通過共享內(nèi)存獲取要讀的block在DataNode磁盤上文件的file descriptor(因為這樣比傳遞文件目錄更安全),然后直接用對應(yīng)的file descriptor建立起本地磁盤輸入流王财,所以目前的short circuit read也是一種zero-copy read卵迂。這需要在DataNode和Client做配置。

增加了Centralized cache的HDFS的讀接口并沒有改變绒净。DFSClient通過RPC獲取LocatedBlock時里面多了個成員表示哪個DataNode把這個block cache到內(nèi)存里面了见咒。如果DFSClient和該block被cache的DataNode在一起,就可以通過zero-copy read大大提升讀效率挂疆。而且即使在讀取的過程中該block被uncache了改览,那么這個讀就被退化成了本地磁盤讀,一樣能夠獲取數(shù)據(jù)缤言。

2.11.3 寫流程

image

寫詳細步驟:

1.客戶端向NameNode發(fā)出寫文件請求宝当。

2.檢查是否已存在文件、檢查權(quán)限胆萧。若通過檢查庆揩,直接先將操作寫入EditLog,并返回輸出流對象跌穗。

注:WAL订晌,write ahead log,先寫Log蚌吸,再寫內(nèi)存锈拨,因為EditLog記錄的是最新的HDFS客戶端執(zhí)行所有的寫操作。如果后續(xù)真實寫操作失敗了羹唠,由于在真實寫操作之前奕枢,操作就被寫入EditLog中了,故EditLog中仍會有記錄佩微,我們不用擔(dān)心后續(xù)client讀不到相應(yīng)的數(shù)據(jù)塊缝彬,因為在第5步中DataNode收到塊后會有一返回確認信息,若沒寫成功喊衫,發(fā)送端沒收到確認信息跌造,會一直重試,直到成功族购。

3.client端按128MB的塊切分文件壳贪。

4.client將NameNode返回的分配的可寫的DataNode列表和Data數(shù)據(jù)一同發(fā)送給最近的第一個DataNode節(jié)點,此后client端和NameNode分配的多個DataNode構(gòu)成pipeline管道寝杖,client端向輸出流對象中寫數(shù)據(jù)违施。client每向第一個DataNode寫入一個packet,這個packet便會直接在pipeline里傳給第二個瑟幕、第三個…DataNode磕蒲。

注:并不是寫好一個塊或一整個文件后才向后分發(fā)

5.每個DataNode寫完一個塊后留潦,會返回確認信息。

注:并不是每寫完一個packet后就返回確認信息辣往,個人覺得因為packet中的每個chunk都攜帶校驗信息兔院,沒必要每寫一個就匯報一下,這樣效率太慢站削。正確的做法是寫完一個block塊后坊萝,對校驗信息進行匯總分析,就能得出是否有塊寫錯的情況發(fā)生许起。

6.寫完數(shù)據(jù)十偶,關(guān)閉輸輸出流。

7.發(fā)送完成信號給NameNode园细。

注:發(fā)送完成信號的時機取決于集群是強一致性還是最終一致性惦积,強一致性則需要所有DataNode寫完后才向NameNode匯報。最終一致性則其中任意一個DataNode寫完后就能單獨向NameNode匯報猛频,HDFS一般情況下都是強調(diào)強一致性狮崩。

在寫數(shù)據(jù)的過程中,如果Pipeline數(shù)據(jù)流管道中的一個DataNode節(jié)點寫失敗了會發(fā)生什問題鹿寻、需要做哪些內(nèi)部處理呢厉亏?如果這種情況發(fā)生,那么就會執(zhí)行一些操作:

首先烈和,Pipeline數(shù)據(jù)流管道會被關(guān)閉,ack queue中的packets會被添加到data queue的前面以確保不會發(fā)生packets數(shù)據(jù)包的丟失皿淋;

接著招刹,在正常的DataNode節(jié)點上的以保存好的block的ID版本會升級——這樣發(fā)生故障的DataNode節(jié)點上的block數(shù)據(jù)會在節(jié)點恢復(fù)正常后被刪除,失效節(jié)點也會被從Pipeline中刪除窝趣;

最后疯暑,剩下的數(shù)據(jù)會被寫入到Pipeline數(shù)據(jù)流管道中的其他兩個節(jié)點中。

如果Pipeline中的多個節(jié)點在寫數(shù)據(jù)是發(fā)生失敗哑舒,那么只要寫成功的block的數(shù)量達到dfs.replication.min(默認為1)妇拯,那么就任務(wù)是寫成功的,然后NameNode后通過一步的方式將block復(fù)制到其他節(jié)點洗鸵,最后事數(shù)據(jù)副本達到dfs.replication參數(shù)配置的個數(shù)越锈。

在一個繁忙的HDFS集群當中,可能會發(fā)生DateNode寫失敗的情況膘滨。此時甘凭,NameNode就會把這個DateNode實例排除掉,去尋找新的可用DateNode火邓。假如集群的可用DateNode數(shù)較少丹弱,找不到新的可用DateNode德撬,文件無法恢復(fù)到要求的副本數(shù),就會導(dǎo)致文件無法再寫入躲胳。

解決辦法有兩個:

  • 增加集群的機器數(shù)量蜓洪。
  • 修改配置,讓寫入的行為發(fā)生改變坯苹。dfs.client.block.write.replace-datanode-on-failure.enable配置默認是true隆檀,表示如果在寫入的pipeline有datanode失敗的時候是否要切換到新的機器。但是如果集群比較小的話北滥,有兩臺機器失敗的話刚操,就沒有其他機器可以切換了,所以把該配置設(shè)置成false后就能解決問題再芋。

2.11.3 讀寫流程如何保證一致性

通過校驗和菊霜。因為每個chunk中都有一個校驗位,一個個chunk構(gòu)成packet济赎,一個個packet最終形成block鉴逞,故可在block上求校驗和。HDFS的client端即實現(xiàn)了對HDFS文件內(nèi)容的校驗和(checksum)檢查司训。

當客戶端創(chuàng)建一個新的HDFS文件時候构捡,分塊后會計算這個文件每個數(shù)據(jù)塊的校驗和,此校驗和會以一個隱藏文件形式保存在同一個HDFS命名空間下壳猜。當client端從HDFS中讀取文件內(nèi)容后勾徽,它會檢查分塊時候計算出的校驗和(隱藏文件里)和讀取到的文件塊中校驗和是否匹配,如果不匹配统扳,客戶端可以選擇從其他 Datanode 獲取該數(shù)據(jù)塊的副本喘帚。

HDFS中文件塊目錄結(jié)構(gòu)具體格式如下:

${dfs.datanode.data.dir}/

├── current

│ ├── BP-526805057-127.0.0.1-1411980876842

│ │ └── current

│ │ ├── VERSION

│ │ ├── finalized

│ │ │ ├── blk_1073741825

│ │ │ ├── blk_1073741825_1001.meta

│ │ │ ├── blk_1073741826

│ │ │ └── blk_1073741826_1002.meta

│ │ └── rbw

│ └── VERSION

└── in_use.lock

in_use.lock表示DataNode正在對文件夾進行操作

rbw是“replica being written”的意思,該目錄用于存儲用戶當前正在寫入的數(shù)據(jù)咒钟。

Block元數(shù)據(jù)文件(*.meta)由一個包含版本吹由、類型信息的頭文件和一系列校驗值組成。校驗和也正是存在其中朱嘴。

2.11.4 透明倾鲫、端到端數(shù)據(jù)加密

2.11.5 多宿主網(wǎng)絡(luò)

2.11.6 歸檔存儲,SSD乌昔,內(nèi)存

HDFS為分離冷熱數(shù)據(jù)提供了支持,通過storagepolicies命令行工具可以指定一個目錄(遞歸)或文件的存儲策略壤追。當然玫荣,必須首先在DateNode啟用存儲策略,并配置不同的存儲介質(zhì)大诸。

  • 存儲類型:ARCHIVE, DISK, SSD and RAM_DISK

HDFS支持異構(gòu)存儲捅厂,DateNode支持多個存儲贯卦,每個存儲對應(yīng)一種存儲介質(zhì)。

ARCHIVE:我理解這泛指高密度歸檔存儲設(shè)備焙贷。

RAM_DISK:要求Client位于DataNode節(jié)點上撵割,因為跨網(wǎng)絡(luò)時延足以抵消內(nèi)存寫入帶來的好處。

image
  • 存儲策略:Hot, Warm, Cold, All_SSD, One_SSD and Lazy_Persist

HDFS定義了集中存儲策略辙芍,

  • Hot - 熱數(shù)據(jù)啡彬,有存儲和計算的雙重用途。所有的副本都存儲在DISK故硅。
  • Cold - 冷數(shù)據(jù)庶灿,數(shù)據(jù)已經(jīng)不再使用,僅僅是歸檔保存吃衅。所有副本存儲在ARCHIVE往踢。
  • Warm - 溫數(shù)據(jù)。部分副本存儲在DISK徘层,其他副本存儲在ARCHIVE峻呕。
  • All_SSD - 所有副本存儲在SSD。
  • One_SSD - 一個副本存儲在SSD趣效,其他副本存在在DISK瘦癌。
  • Lazy_Persist - 用于在內(nèi)存中寫入具有單個副本的塊。副本首先在RAM_DISK中寫入跷敬,然后在DISK中惰性持久化讯私。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市西傀,隨后出現(xiàn)的幾起案子妄帘,更是在濱河造成了極大的恐慌,老刑警劉巖池凄,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鬼廓,居然都是意外死亡肿仑,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門碎税,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尤慰,“玉大人,你說我怎么就攤上這事雷蹂∥岸耍” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵匪煌,是天一觀的道長责蝠。 經(jīng)常有香客問我党巾,道長,這世上最難降的妖魔是什么霜医? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任齿拂,我火速辦了婚禮,結(jié)果婚禮上肴敛,老公的妹妹穿的比我還像新娘署海。我一直安慰自己,他們只是感情好医男,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布砸狞。 她就那樣靜靜地躺著,像睡著了一般镀梭。 火紅的嫁衣襯著肌膚如雪刀森。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天丰辣,我揣著相機與錄音撒强,去河邊找鬼。 笑死笙什,一個胖子當著我的面吹牛飘哨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播琐凭,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼芽隆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了统屈?” 一聲冷哼從身側(cè)響起胚吁,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎愁憔,沒想到半個月后腕扶,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡吨掌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年半抱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片膜宋。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡窿侈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出秋茫,到底是詐尸還是另有隱情史简,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布肛著,位于F島的核電站圆兵,受9級特大地震影響跺讯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜衙傀,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一抬吟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧统抬,春花似錦火本、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至金麸,卻和暖如春擎析,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背挥下。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工揍魂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人棚瘟。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓现斋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親偎蘸。 傳聞我的和親對象是個殘疾皇子庄蹋,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容