hadoop筆記-hdfs文件讀寫

概念

文件系統

磁盤進行讀寫的最小單位:數據塊,文件系統構建於磁盤之上,文件系統的塊大小是磁盤塊的整數倍。前端

文件系統塊通常爲幾千字節,磁盤塊通常512字節。node

hdfs的block、pocket、chunk

  • block面試

 hdfs的塊,常說的block,是這三個裏最大的單位。默認128MB(配置參數:dfs.block.size)網絡

128MB的緣由:塊過小會增長尋址時間;塊太大會減小Map的任務(一般一個Map只處理一個塊的數據)。併發

注:文件的大小小於一個block並不會佔據整個block的空間,如一個1M的文件存儲在128MB的block中時,並非佔用128MB的的磁盤空間,而是1MB。異步

  • pocket分佈式

這三個裏面中等大小的單位,DFSClient流向DataNode的粒度,以dfs.write.packet.size參數爲參考值,默認是64K;注:這個參數爲參考值,是指真正在進行數據傳輸時,會以它爲基準進行調整,調整的緣由是一個packet有特定的結構,調整的目標是這個packet的大小恰好包含結構中的全部成員,同時也保證寫到DataNode後當前block的大小不超過設定值;oop

  • chunkspa

是最小的一個單位,它是DFSClient到DataNode數據傳輸中進行數據校驗的粒度,由io.bytes.per.checksum參數決定,默認是512B;事實上一個chunk還包含4B的校驗值,於是chunk寫入packet時是516B;數據與檢驗值的比值爲128:1,因此對於一個128M的block會有一個1M的校驗文件與之對應;設計

分佈式文件系統使用塊的好處

  1. 一個文件的大小能夠大於網絡中任意磁盤的容量。
  2. 使用抽象快而不是整個文件做爲存儲,大大簡化了存儲子系統的設計。

文件讀

  1.  客戶端調用FileSyste對象的open()方法打開要讀取的文件。
  2. DistractedFileSystem經過遠程過程調用(RPC)來調用namenode,以獲取文件的其實位置。對於每個塊,namenode返回該副本的datanode的地址。這些datanode根據它們與客戶端的距離來排序(根據集羣的網絡拓撲)。若是客戶端自己就是一個datanode,那麼會從保存相應數據塊副本的本地datanode讀取數據。
  3. DistrubutedFileSystem返回一個FSDataInputStream對象(支持文件定位的數據流)給客戶端便讀取數據。FSDataInputStream轉而封裝DFSInputStream對象,它管理datanode和namenode的I/O。接着客戶端對這個數據流調用read()。
  4. 存儲着文件的塊的datanode地址的DFSInputStream會鏈接距離最近的文件中第一個塊所在的datanode。反覆調用read()將數據從datanode傳輸到客戶端。
  5. 讀到塊的末尾時,DFSInputStream關閉與前一個datanode的鏈接,而後尋找下一個塊的最佳datanode。
  6. 客戶端的讀寫順序時按打開的datanode的順序讀的,一旦讀取完成,就對FSDataIputStream調用close()方法。

在讀取數據的時候,datanode一旦發生故障,DFSInputStream會嘗試從這個塊鄰近的datanode讀取數據,同時也會記住哪一個故障的datanode,並把它通知到namenode。

文件寫

  1. 客戶端經過調用DistributedFileSystem的create()方法新建文件。
  2. DistributedFileSystem對namenode建立RPC調用,在文件系統的命名空間新建一個文件,此時該文件尚未相應的數據塊。
  3. namenode執行各類檢查以確保這個文件不存在以及客戶端新建文件的權限。若是各類檢查都經過,就建立;不然拋出IO異常。DistributedFileSystem向客戶端返回一個FSDataOutputStream對象,由此客戶端開始寫入數據,FSDataOutputStream會封裝一個DFSoutPutstream對象,負責namenode和datanode之間的通訊。
  4. DFSOutPutstream將數據分紅一個個的數據包(packet),並寫入內部隊列,即數據隊列(data queue),DataStreamer處理數據隊列,它將選擇一組datanode,並據此要求namenode從新分配新的數據塊。這一組datanode構成管線,假設副本數是3,因此管線有3個節點。DataStreamer將數據包流式傳輸到第一個datanode,該datanode存儲數據包併發送給第二個datanode。。。依次類推,直到最後一個。【面試題】
  5. DFSOutPutstream維護了一個數據包隊列等待datanode的收到確認回執,成爲確認隊列(ack queue),每個datanode收到數據包後都會返回一個確認回執,而後放到這個ack queue,等全部的datanode確認信息後,該數據包纔會從隊列ack queue刪除。
  6. 完成數據寫入後,對數據流調用close。

在寫入過程當中datanode發生故障,將執行如下操做

1)關閉管線,把隊列的數據報都添加到隊列的最前端,以確保故障節點下游的datanode不會漏掉任何一個數據包。

2)爲存儲在另外一個正常的datanode的當前數據塊指定一個新的標識,並把標識發送給namenode,以便在datanode恢復正常後能夠刪除存儲的部分數據塊。

3)從管線中刪除故障datanode,基於正常的datanode構建一條新管線。餘下的數據塊寫入管線中正常的datanode。namenode注意到塊副本數量不足,會在另外一個節點上建立一個新的副本。後續的數據塊正常接受處理。

若是多個datanode發生故障(很是少見)

只要寫入了dfs.namenode.replication.min的副本數(默認1),寫操做就會成功,而且這個塊能夠在集羣中異步複製,直到達到其目的的副本數(dfs.replication的默認值3)

 

 

參考

hadoop權威指南

相關文章
相關標籤/搜索