淺談HDFS的文件讀取與寫入

HDFS文件讀取:

  • 數據讀取的步驟:
  1. 客戶端通過FileSystem對象(抽象類,一般通過這個來調用方法),open()方法打開需要讀取的文件,HDFS中用DistributedFileSystem實現FileSystem的open()方法,通過遠程調用(RPC)調用namenode,namenode告訴它存放該塊複本的datanode地址
  2. datanode通過網絡拓撲找到距離客戶端最近的datanode並排序
  3. open()方法返回一個FSDataInputStream對象,客戶端對FSDataInputStream的read()用來找到對應的最佳datanode,通過反覆調用read()將結果告訴給客戶端,到達塊的末端時斷開datanode之間的連接,再去找下一塊的最佳datanode
  4. 最後,客戶端調用FSDataInputStream close()完成數據讀取
  • 客戶端讀取HDFS文件系統中的數據圖:
    在這裏插入圖片描述
  • 用API寫個簡單的文件讀取例子
    @Test
    public void openTest() throws Exception {
        FSDataInputStream in = fileSystem.open(new Path("/hdfsapi/test/aa.txt"));
        //講讀出的數據輸出到控制檯上
        IOUtils.copyBytes(in,System.out,1024);
        //關閉數據流
        IOUtils.closeStream(in);
    }

Hadoop中的網絡距離:

默認情況下,所有節點再同一數據中心的同一機架上。
圖中數據中心是date center,機架是rack,節點是node,d代表兩結點之間的網絡距離。

1)同一節點上的進程: d(/dc1/rack1/node1 , /dc1/rack1/node1) = 0
2)同一機架上的不同節點: d(/dc1/rack1/node1 , /dc1/rack1/node2) = 2
3)同一數據中心的不同機架上的節點: d(/dc1/rack1/node1 , /dc1/rack2/node3) = 4
4)不同數據中心的節點: d(/dc1/rack1/node1 , /dc2/rack3/node4) = 6
在這裏插入圖片描述

  • 讀取數據過程出現錯誤的處理:
    如果在讀取數據過程中DFSInputStream(封裝的FSDataInputStream,負責namenode和datanode之間的通信)與datanode通信時遇到錯誤,會從這個塊的另一個最鄰近datanode讀取數據,同時記住故障datanode。DFSInputStream會是試圖從其他datanode讀取其複本,也將損壞塊通知給namenode。

文件寫入

  • 數據寫入的步驟:
  1. 客戶端通過FileSystem對象(抽象類),DistributedFileSystem對象實現的create()方法新建文件,新建文件時需要確認客戶端有權限以及文件是否已經存在,如果存在就會返回IOException異常
  2. 創建文件成功後返回FSDataOutputStream對象,客戶端通過調用write()向datanode執行寫入操作,連接DataNode時DFSOutputStream(FSDataOutputStream封裝後,負責namenode和datanode之間的通信)。把數據分爲一個個數據包並寫入內部隊列,叫“數據隊列”(data queue),這一步由DataStreamer完成,它還負責選出合適存儲數據複本的一組datanode,並告訴namenode分配所需的新的數據塊
  3. 假設複本係數爲3,則一個管線中有三個節點,DataStreamer將數據包流式傳輸到管線中第一個datanode,datanode存儲數據包並將它發送到管線中的第二個datanode,按照同樣的方法發送到最後一個datanode中
  4. 最後一個datanode再向前一個datanode發送確認回執,叫“確認隊列”(ack queue)並講確認隊列返回給DFSOutputStream,直至收到所有datanode確認回執
  5. 客戶端調用FSDataInputStream close(),完成數據寫入
  6. 再完成數據寫入前,namenode需要確認(complete)文件寫入已完成,等待數據塊最小量的複製
    在這裏插入圖片描述
  • 文件寫入的例子
@Test
    public void outputTest() throws Exception {
        InputStream input = new BufferedInputStream(new FileInputStream(new File("E:\\ComputerQQDownload\\jdk-8u192-linux-x64.tar.gz")));

        FSDataOutputStream out = fileSystem.create(new Path("/hdfsapi/test/jdk.tgz"), new Progressable() {
            @Override
            public void progress() {
                System.out.print(">");
            }
        });

        IOUtils.copyBytes(input, out, 4096);
        out.close();
        input.close();
    }

複本怎麼存

  • 第一個複本時隨機的存放再機架上的某一個節點
  • 第二個複本是存放在同一數據中心的不同機架上的某一節點上,這個過程叫離架
  • 第三個複本與第二個存放在同一機架上的某一節點上
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章