摘要:從HDFS的寫入和讀取中,我們能學習到什麼?
本文分享自華為雲社群《從HDFS的寫入和讀取中,我們能學習到什麼》,作者: breakDawn 。
最近開發過程涉及了一些和檔案讀取有關的問題,於是對hdfs的讀取機制感到興趣,順便深入學習了一下。
寫入
- 客戶端向NameNode發出寫檔案請求,告訴需要寫的檔名和路徑、使用者
- NameNode檢查是否已存在檔案、檢查許可權。如果通過,會返回一個輸出流物件
- 注意此時會按照“日誌先行“原則,寫入NameNode的editLog
- 客戶端按照128MB的大小切分檔案。 也就是block大小
- 客戶端把nameNode傳來的DataNode列表和Data資料一同傳送給 最近的第一個DataNode節點。
- 第一個dataNode節點收到資料和DataNode列表時, 會先根據列表,找到下一個自己要連線的最近DataNode, 刪除自己後,再一樣往下發。以此類推,發完3臺或者N臺。
- 傳輸單位是packet,包,比block小一點。
- dataNode每寫完一個block塊, 則返回ACK資訊給上一個節點進行確認。(注意是寫完block才確認)
- 寫完資料, 關閉輸出流, 傳送完成資訊給DataNode
寫過程的核心總結:
- 客戶端只向一個dataNode寫資料,然後下一個dataNode接著往另一個dataNode寫,串聯起來。
- 按128MB分block。 每次傳資料按pack傳。 校驗按照chunk 校驗,每次chunk都會寫入pack。
- 寫完block才發ACK確認。
Q: NameNode的editlog有什麼用?怎麼起作用的?
A:作用:
- 硬碟中需要有一份後設資料的映象——FSImage
- 每次要修改後設資料就資訊時,必須得改檔案(hdfs沒有資料庫)
- 可能會比較久,改的時候如果斷電了,就丟失這個操作了
為了避免丟失,引入editlog,每次修改後設資料前,先追加方式寫入editlog, 然後再處理,這樣即使斷電了也能修復。
一般都是那些更改操作有斷開風險,為了確保能恢復,都會引入這類操作。
Q: 什麼時候傳送完成訊號? 全部節點都寫入完成嗎
A:傳送完成訊號的時機取決於叢集是強一致性還是最終一致性,強一致性則需要所有DataNode寫完後才向NameNode彙報。最終一致性則其中任意一個DataNode寫完後就能單獨向NameNode彙報,HDFS一般情況下都是強調強一致性
Q: 怎麼驗證寫入時的資料完整性?
A:
- 因為每個chunk中都有一個校驗位,一個個chunk構成packet,一個個packet最終形成block,故可在block上求校驗和。
- 當客戶端建立一個新的HDFS檔案時候,分塊後會計算這個檔案每個資料塊的校驗和,此校驗和會以一個隱藏檔案形式儲存在同一個 HDFS 名稱空間下。就是.meta檔案
- 當client端從HDFS中讀取檔案內容後,它會檢查分塊時候計算出的校驗和(隱藏檔案裡)和讀取到的檔案塊中校驗和是否匹配,如果不匹配,客戶端可以選擇從其他 Datanode 獲取該資料塊的副本。
Q: 寫入時怎麼確定最近節點?
A:按照按照hadoop時設定的機架、資料中心、節點來估算
假設有資料中心d1機架r1中的節點n1。該節點可以表示為/d1/r1/n1。利用這種標記,這裡給出四種距離描述。
- Distance(/d1/r1/n1, /d1/r1/n1)=0(同一節點上的程式)
- Distance(/d1/r1/n1, /d1/r1/n2)=2(同一機架上的不同節點)
- Distance(/d1/r1/n1, /d1/r3/n2)=4(同一資料中心不同機架上的節點)
- Distance(/d1/r1/n1, /d2/r4/n2)=6(不同資料中心的節點)
讀取
讀取就比較簡單了,沒有那種複雜的序列過程。NameNode直接告訴客戶端去哪讀就行了。
- client訪問NameNode,查詢後設資料資訊,獲得這個檔案的資料塊位置列表,返回輸入流物件。
- 就近挑選一臺datanode伺服器,請求建立輸入流 。
- DataNode向輸入流中中寫資料,以packet為單位來校驗。
- 關閉輸入流