Hadoop 源碼學習筆記(4)--Hdfs 數(shù)據(jù)讀寫流程分析

Hdfs 的數(shù)據(jù)模型

在對讀寫流程進行分析之前,我們需要先對 Hdfs 的數(shù)據(jù)模型有一個簡單的認知祷蝌。

數(shù)據(jù)模型

如上圖所示害幅,在 NameNode 中有一個唯一的 FSDirectory 類負責維護文件系統(tǒng)的節(jié)點關系练慕。文件系統(tǒng)中的每個路徑會被抽象為一個 INode 對象。在 FSDirectory 中有一個叫做 rootDir 的 INodeDirectory 類砂吞,繼承自 INode 類,它代表著整個文件系統(tǒng)的根節(jié)點崎溃。

常用的 INode 節(jié)點有 INodeDirectory, INodeFile, INodeReference 三種蜻直。

  1. INodeDirectory 類代表著對目錄對象的抽象,在類中有一個 List<INode> 對象 children 負責保存當前節(jié)點的子節(jié)點信息袁串。
  2. INodeFile 類代表著對文件對象的抽象概而,對于一個大文件, Hdfs 可能將其拆分為多個小文件進行存儲囱修,在這里的 blocks 對象是一個數(shù)據(jù)對象赎瑰,代表著小文件的具體存放位置信息。
  3. INodeReference 類可以理解成 Unix 系統(tǒng)中的硬鏈接破镰。當文件系統(tǒng)中可能出現(xiàn)多個 path 地址對應同一個 INode 節(jié)點時餐曼,會構(gòu)造出 INodeReference 對象。例如我們對 /abc/foo 構(gòu)造一個快照 s0, 則 然后將 /abc/foo mv 到另一個路徑 /xyz/bar啤咽,此時 /xyz/bar 和 /abc/.snapshot/s0/foo 雖然是不同的路徑晋辆,但是對應著同一個 block 地址。

Hdfs 的 IO 操作

當通過 hdfs dfs 進行文件 IO 操作時宇整,會根據(jù)配置文件中 fs.defaultFS 的配置信息構(gòu)造出一個 FileSystem 對象瓶佳。具體的文件操作指令,通過 FileSystem 中對應的接口進行訪問鳞青。

對于 hdfs 而言霸饲,他的默認 FileSystem 實現(xiàn)類是 DistributedFileSystem, 在 DistribtedFileSystem 中有一個 DFSClient 對象为朋。這個對象使用前一篇文章中介紹的內(nèi)部 RPC 通信機制,構(gòu)造了一個 namenode 的代理對象厚脉,負責同 NameNode 間進行 RPC 操作习寸。

Hdfs 的文件寫入流程

PUT

以 PUT 操作為例:

  1. 當接收到 PUT 請求時,嘗試在 NameNode 中 create 一個新的 INode 節(jié)點傻工,這個節(jié)點是根據(jù) create 中發(fā)送過去的 src 路徑構(gòu)建出的目標節(jié)點,如果發(fā)現(xiàn)節(jié)點已存在或是節(jié)點的 parent 存在且不為 INodeDirectory 則異常中斷霞溪,否則則返回包含 INode 信息的 HdfsFileStatus 對象。
  2. 使用 HdfsFileStatus 構(gòu)造一個實現(xiàn)了 OutputStream 接口的 DFSOutputStream 類中捆,通過 nio 接口將需要傳輸?shù)臄?shù)據(jù)寫入 DFSOutputStream鸯匹。
  3. DFSOutputStream 中寫入的數(shù)據(jù)被以一定的 size(一般是 64 k)封裝成一個 DFSPacket,壓入 DataStreamer 的傳輸隊列中。
  4. DataStreamer 是 Client 中負責數(shù)據(jù)傳輸?shù)莫毩⒕€程泄伪,當發(fā)現(xiàn)隊列中有 DFSPacket 時殴蓬,先通過 namenode.addBlockNameNode 中獲取可供傳輸?shù)?DataNode 信息,然后同指定的 DataNode 進行數(shù)據(jù)傳輸蟋滴。
  5. DataNode 中有一個專門的 DataXceiverServer 負責接收數(shù)據(jù)染厅,當有數(shù)據(jù)到來時,就進行對應的 writeBlock 寫入操作津函,同時如果發(fā)現(xiàn)還有下游的 DataNode 同樣需要接收數(shù)據(jù)肖粮,就通過管道再次將發(fā)來的數(shù)據(jù)轉(zhuǎn)發(fā)給下游 DataNode,實現(xiàn)數(shù)據(jù)的備份球散,避免通過 Client 一次進行數(shù)據(jù)發(fā)送尿赚。

整個操作步驟中的關鍵步驟有 NameNode::addBlock 以及 DataNode::writeBlock, 接下來會對這兩步進行詳細分析。

NameNode::addBlock 解析

在上面的數(shù)據(jù)模型中我們看到蕉堰,對于一個 INodeFile 節(jié)點凌净,我們可能會根據(jù)其數(shù)據(jù)大小將其拆分成多個 Block,因此當傳輸新文件或者文件傳輸尺寸已經(jīng)超過 blockSize 的時候屋讶,就需要通過 addBlock 獲取新的傳輸?shù)刂贰?/p>

NameNode 中 addBlock 的實現(xiàn)路徑在 FSNamesystem::getAdditionalBlock 中冰寻,這里先通過 FSDirWriteFileOp::validateAddBlock 判斷是否是因為延遲或異常問題導致的無效請求,如果不是皿渗,則通過 FSDirWriteFileOp.chooseTargetForNewBlock 選取新 Block 的目標 DataNode斩芭,

chooseTargetForNewBlock 的具體算法由 BlockPlacementPolicy 完成,默認情況下會優(yōu)先選擇 client 自身所在機器作為 target乐疆,如果自身機器不是 DataNode划乖,則會優(yōu)先選擇和當前機器處于同一機架( rack )中的 DataNode,以提升數(shù)據(jù)傳輸效率挤土。

確定寫入的 DataNode 后琴庵,通過 FSDirWriteFileOp::storeAllocatedBlock 構(gòu)造 Block 對象,并放入 src 對應的 INodeFile 中。

DataNode::writeBlock 解析

DataNode 中的 DataXceiverServer 負責接收從 Client 發(fā)送來的數(shù)據(jù)傳輸請求迷殿。當有新的鏈接接通時儿礼,會構(gòu)造一個 DataXceiver 線程進行數(shù)據(jù)接收。

DataXceiver::writeBlock 中庆寺,如果發(fā)現(xiàn) targets.length > 0蚊夫,則說明還有下游的 DataNode 需要接收數(shù)據(jù)傳輸,這時候會和 Client 一樣構(gòu)造出一個鏈接到下游 DataNode 的 socket 鏈接懦尝,通過 new Sender(mirrorOut).writeBlock 將數(shù)據(jù)寫入下游知纷。

Hdfs 的文件讀取流程

GET

GET 操作的流程,相對于 PUT 會比較簡單陵霉,先通過參數(shù)中的來源路徑從 NameNode 對應 INode 中獲取對應的 Block 位置屈扎,然后基于返回的 LocatedBlocks 構(gòu)造出一個 DFSInputStream 對象。在 DFSInputStream 的 read 方法中撩匕,根據(jù) LocatedBlocks 找到擁有 Block 的 DataNode 地址,通過 readBlock 從 DataNode 獲取字節(jié)流墨叛。

Hdfs 的文件重命名流程

MV 操作只涉及對文件名稱或路徑的更改止毕,因此他的主要步驟集中在 NameNode 端,Client 端只是通過 RPC 調(diào)用 NameNode::rename

MV

從活動圖中我們看到漠趁,整個 rename 的操作分了兩步扁凛,第一步是 removeSrc4OldRename,將 src 從 FSDirectory 中移除闯传,第二步是 addSourceToDestination 谨朝,將之前移除的 src 的 INode,重新根據(jù) dst 的路徑添加到 FSDirectory 中甥绿,完成整個重命名流程字币。

總結(jié)

HDFS 中的文件 IO 操作主要是發(fā)生在 Client 和 DataNode 中。

NameNode 作為整個文件系統(tǒng)的 Namesystem 負責管理整個文件系統(tǒng)的路徑樹共缕,當需要新建文件或讀取文件時洗出,會從文件樹中讀取對應的路徑節(jié)點的 Block 信息,發(fā)送回 Client 端图谷。 Client 通過從返回數(shù)據(jù)中得到的 DataNode 和 Block 信息翩活,直接從 DataNode 中進行數(shù)據(jù)讀取。

整個數(shù)據(jù) IO 流程中便贵,NameNode 只負責管理節(jié)點和 DataNode 的對應關系菠镇,涉及到 IO 操作的行為少,從而將整個文件傳輸壓力從 NameNode 轉(zhuǎn)移到了 DataNode 中承璃。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末利耍,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌堂竟,老刑警劉巖魂毁,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異出嘹,居然都是意外死亡席楚,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門税稼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烦秩,“玉大人,你說我怎么就攤上這事郎仆≈混簦” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵扰肌,是天一觀的道長抛寝。 經(jīng)常有香客問我,道長曙旭,這世上最難降的妖魔是什么盗舰? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮桂躏,結(jié)果婚禮上钻趋,老公的妹妹穿的比我還像新娘。我一直安慰自己剂习,他們只是感情好蛮位,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鳞绕,像睡著了一般失仁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上们何,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天舒憾,我揣著相機與錄音椒涯,去河邊找鬼费什。 笑死钳吟,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的贴见。 我是一名探鬼主播烘苹,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼片部!你這毒婦竟也來了镣衡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎廊鸥,沒想到半個月后望浩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡惰说,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年磨德,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吆视。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡典挑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出啦吧,到底是詐尸還是另有隱情您觉,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布授滓,位于F島的核電站琳水,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏般堆。R本人自食惡果不足惜炫刷,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望郁妈。 院中可真熱鬧,春花似錦绍申、人聲如沸噩咪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽胃碾。三九已至,卻和暖如春筋搏,著一層夾襖步出監(jiān)牢的瞬間仆百,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工奔脐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留俄周,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓髓迎,卻偏偏與公主長得像峦朗,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子排龄,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

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