HDFS的數據寫入過程

HDFS寫文件流程:

1.客戶端通過調用DistributedFileSystem的create方法創建新文件

2.DistributedFileSystem通過RPC調用namenode去創建一個沒有blocks關聯的新文件,創建前,namenode會做各種校驗,比如文件是否存在,客戶端有無權限去創建等。如果校驗通過,namenode就會記錄下新文件,否則就會拋出IO異常.

3.這樣會返回FSDataOutputStream的對象,FSDataOutputStream被封裝成DFSOutputStream.
DFSOutputStream可以協調namenode和datanode。客戶端開始寫數據到DFSOutputStream,
DFSOutputStream會把數據切成一個個小packet,然後排成隊列data quene。

4.DataStreamer會去處理接受data queue,他先問詢namenode這個新的block最適合存儲的在哪幾個datanode裏,如果副本數是3,那麼就找到3個最適合的datanode,把他們排成一個pipeline.DataStreamer把packet按隊列輸出到管道的第一個datanode中,第一個datanode又把packet輸出到第二個datanode中,以此類推。

5.DFSOutputStream還有一個隊列叫ack queue,也是由packet組成,等待收到datanode的響應,當pipeline中的所有datanode都表示已經收到的時候,這時akc queue纔會把對應的packet包移除掉。

如果在寫的過程中某個datanode發生錯誤,會採取以下幾步:
1) pipeline被關閉掉;
2)爲了防止丟包ack queue裏的packet會同步到data queue裏;
3)把產生錯誤的datanode上當前在寫但未完成的block刪掉;
4)block剩下的部分被寫到剩下的兩個正常的datanode中;
5)namenode找到另外的datanode去創建這個塊的複製。當然,這些操作對客戶端來說是無感知的。
6.客戶端完成寫數據後調用close方法關閉寫入流
7.DataStreamer把剩餘得包都刷到pipeline裏然後等待ack信息,收到最後一個ack後,通知datanode把文件標示爲已完成。

另外要注意得一點,客戶端執行write操作後,寫完得block纔是可見的,正在寫的block對客戶端是不可見的,只有調用sync方法,客戶端才確保該文件被寫操作已經全部完成,當客戶端調用close方法時會默認調用sync方法。是否需要手動調用取決你根據程序需要在數據健壯性和吞吐率之間的權衡。

代碼:
1.public FSDataOutputStream create(Path f) throws IOException {
return create(f, true);
 }
2.public FSDataOutputStream create(Path f, boolean overwrite)
      throws IOException {
return create(f, overwrite, 
                  getConf().getInt("io.file.buffer.size", 4096),
                  getDefaultReplication(f),
                  getDefaultBlockSize(f));
}
3.public abstract FSDataOutputStream create(Path f,
 FsPermission permission,//權限
 boolean overwrite,//是否覆蓋
 int bufferSize,
 short replication,//副本
 long blockSize,//塊的大小
 Progressable progress//進度
 ) throws IOException;
4.public FSDataOutputStream create(Path f, FsPermission permission,
      boolean overwrite, int bufferSize, short replication, long blockSize,
      Progressable progress) throws IOException {
return this.create(f, permission,
        overwrite ? EnumSet.of(CreateFlag.CREATE, CreateFlag.OVERWRITE)
            : EnumSet.of(CreateFlag.CREATE), bufferSize, replication,
        blockSize, progress, null);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章