hadoop筆記-hdfs文件讀寫


概念

文件系統

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

文件系統塊一般為幾千字節,磁盤塊一般512字節。

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的大小不超過設定值;

  • chunk

是最小的一個單位,它是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權威指南

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM