3.6 數(shù)據(jù)流
3.6.1 剖析文件讀取
客戶端讀取HDFS數(shù)據(jù).png
- 1、客戶端調(diào)用
DistributedFileSystem.open
方法以打開(kāi)希望讀取的文件,DistributedFileSystem初始化的時(shí)候(參見(jiàn):java.util.ServiceLoader加載服務(wù)實(shí)現(xiàn)類(lèi))創(chuàng)建了一個(gè)DFSClient
實(shí)例,DFSClient
通過(guò)RPC向namenode發(fā)送請(qǐng)求獲取文件塊位置吨凑,對(duì)于每個(gè)數(shù)據(jù)塊,namenode返回該塊所有復(fù)本datanode地址,這些datanode根據(jù)它們與客戶端的距離排序逃沿,若客戶端本身就是一個(gè)datanode婴渡,那么該客戶端會(huì)從本地讀取數(shù)據(jù)。- 2凯亮、
DistributedFileSystem.open
返回一個(gè)FSDataInputStream
對(duì)象边臼,該對(duì)象封裝了一個(gè)DFSInputStream
,DFSInputStream
封裝了DFSClient假消、Datanode硼瓣、LocatedBlock
;- 3置谦、
FSDataInputStream.read
堂鲤,反復(fù)調(diào)用,達(dá)到塊末端媒峡,DFSInputStream
關(guān)閉與datanode連接瘟栖,尋找下一個(gè)塊的最佳datanode。若DFSInputStream
與datanode通信時(shí)發(fā)生錯(cuò)誤谅阿,會(huì)嘗試從鄰近datanode讀取數(shù)據(jù)半哟。
可以將namenode理解為服務(wù)發(fā)現(xiàn)組件,datanode為真正服務(wù)響應(yīng)組件签餐。
- 帶寬很稀缺寓涨,將兩節(jié)點(diǎn)間帶寬作為距離的衡量標(biāo)準(zhǔn)。
如下場(chǎng)景氯檐,可用帶寬依次遞減:
distance(/d1/r1/n1, /d1/r1/n1) = 0(同一節(jié)點(diǎn)上進(jìn)程)
distance(/d1/r1/n1, /d1/r1/n2) = 2(同機(jī)架不同節(jié)點(diǎn))
distance(/d1/r1/n1, /d1/r2/n3) = 4(同數(shù)據(jù)中心不同機(jī)架)
distance(/d1/r1/n1, /d2/r3/n4) = 6(不同數(shù)據(jù)中心)
3.6.2 剖析文件寫(xiě)入
HDFS文件寫(xiě)入.png
- 1戒良、
DistributedFileSystem.create
創(chuàng)建文件,DistributedFileSystem
向namenode發(fā)送文件創(chuàng)建RPC請(qǐng)求冠摄,namenode檢查文件是否存在及用戶是否有創(chuàng)建文件權(quán)限糯崎,若不通過(guò),拋出IO異常- 2河泳、
DistributedFileSystem
返回一個(gè)FSDataOutputStream
沃呢,其封裝了一個(gè)DFSOutputStream
,該對(duì)象負(fù)責(zé)datanode與namenode間通信- 3拆挥、客戶端寫(xiě)入數(shù)據(jù)時(shí)薄霜,
DFSOutputStream
將它分成一個(gè)個(gè)數(shù)據(jù)包,并寫(xiě)入內(nèi)部隊(duì)列(數(shù)據(jù)隊(duì)列data queue)纸兔,DataStreamer
處理數(shù)據(jù)隊(duì)列惰瓜,先挑選一組適合存儲(chǔ)數(shù)據(jù)復(fù)本的datanode,并據(jù)此要求namenode分配新的數(shù)據(jù)塊食拜,這組datanode構(gòu)成一個(gè)管線鸵熟,DataStreamer
將數(shù)據(jù)包流式傳輸?shù)降谝粋€(gè)datanode,該datanode存儲(chǔ)數(shù)據(jù)包并將它發(fā)送到第二個(gè)datanode负甸,同樣第二個(gè)往第三個(gè)datanode傳輸數(shù)據(jù)流强。- 4痹届、
DFSOutputStream
維護(hù)一個(gè)內(nèi)部數(shù)據(jù)包隊(duì)列(確認(rèn)隊(duì)列ack queue),管道中所有datanode發(fā)送ack消息后打月,數(shù)據(jù)包才從隊(duì)列移除队腐。
復(fù)本存放
- 1、運(yùn)行客戶端的節(jié)點(diǎn)存放第一個(gè)復(fù)本奏篙,若客戶端運(yùn)行于集群之外柴淘,則隨機(jī)選擇一個(gè)節(jié)點(diǎn),系統(tǒng)會(huì)盡量避免選擇磁盤(pán)太滿或太忙節(jié)點(diǎn)秘通;
- 2为严、第2個(gè)復(fù)本存放于不同機(jī)架隨機(jī)節(jié)點(diǎn)(離架)
- 3、第3個(gè)復(fù)本與第2個(gè)復(fù)本同一個(gè)機(jī)架肺稀,不同節(jié)點(diǎn)
- 4第股、其他節(jié)點(diǎn)隨機(jī)存放,盡量不在同一機(jī)架存放太多復(fù)本
3.6.3 一致模型(coherency model)
- 1话原、新建文件夕吻,立即可見(jiàn)
- 2、寫(xiě)入文件內(nèi)容(即使已刷新并存儲(chǔ)繁仁,
out.flush()
)涉馅,不保證立即可見(jiàn),當(dāng)寫(xiě)入的數(shù)據(jù)超過(guò)一個(gè)塊黄虱,第一個(gè)塊對(duì)新reader可見(jiàn)稚矿,正在寫(xiě)入的塊對(duì)其他reader不可見(jiàn)。
兩種強(qiáng)刷緩存至所有datanode手段
FSDataInputStream.hflush()
后悬钳,FSDataInputStream.close()
隱含執(zhí)行了hflush()
方法盐捷,HDFS保證文件中到目前為止寫(xiě)入的數(shù)據(jù)均到達(dá)所有datanode寫(xiě)入管道并對(duì)所有reader可見(jiàn)偶翅,不保證數(shù)據(jù)寫(xiě)入磁盤(pán)默勾,可能丟失;FSDataInputStream.hsync()
后聚谁,刷新到磁盤(pán)母剥。
調(diào)用hflush
存在額外性能開(kāi)銷(xiāo),hsync
性能開(kāi)銷(xiāo)更大形导,需要在數(shù)據(jù)魯棒性和性能之間取得平衡环疼。