六、HDFS 的數據流

一、 HDFS 的IO操作

1.1 上傳文件

```
@Test
public void testUploadFile() throws Exception {
    FileInputStream fis = new FileInputStream("D:" + File.separator + "Hadoop_Test.txt");
    FSDataOutputStream fos = fs.create(new Path("/user/kino/idea/Hadoop_Test"));
    IOUtils.copyBytes(fis, fos, conf);
    IOUtils.closeStream(fos);
    IOUtils.closeStream(fis);
}
```

1.2 文件下載(完整下載)

@Test
public void testDownloadFile() throws Exception {
    /**
     *  Path: HDFS 文件系統上的文件路徑;
     *  bufferSize: 要使用的緩衝區的大小, 並不是要將文件下載多大, 默認 4K;
     */
    FSDataInputStream fis = fs.open(new Path("/user/kino/input/hadoop-2.7.2.tar.gz"));
    FileOutputStream fos = new FileOutputStream("D:\\hadoop-2.7.2.tar1.gz");
    IOUtils.copyBytes(fis, fos, conf);
    IOUtils.closeStream(fos);
    IOUtils.closeStream(fis);
}

1.3 文件下載(分塊(Block)下載)

讀取大文件(超過 128M 的文件)
在這裏插入圖片描述

  1. 讀取第一塊(Block)
    @Test
    public void testDownloadFileToBlockOne() throws Exception {
       /**
        *  Path: HDFS 文件系統上的文件路徑;
        *  bufferSize: 要使用的緩衝區的大小, 並不是要將文件下載多大, 默認 4K;
        */
       FSDataInputStream fis = fs.open(new Path("/user/kino/input/hadoop-2.7.2.tar.gz"));
       FileOutputStream fos = new FileOutputStream("D:\\hadoop-2.7.2.tar1.gz");
    
       byte[] b = new byte[1024];
       for (int i = 0; i < 1024*128; i++) {
           fis.read(b);
           fos.write(b);
       }
       IOUtils.closeStream(fos);
       IOUtils.closeStream(fis);
    }
    

在這裏插入圖片描述
2. 讀取第二塊(Block)

@Test
public void testDownloadFileToBlockTwo() throws Exception {
    /**
     *  Path: HDFS 文件系統上的文件路徑;
     *  bufferSize: 要使用的緩衝區的大小, 並不是要將文件下載多大, 默認 4K;
     */
    FSDataInputStream fis = fs.open(new Path("/user/kino/input/hadoop-2.7.2.tar.gz"));
    FileOutputStream fos = new FileOutputStream("D:\\hadoop-2.7.2.tar2.gz");

    fis.seek(1024*1024*128);
    IOUtils.copyBytes(fis, fos, conf);
    IOUtils.closeStream(fos);
    IOUtils.closeStream(fis);
}

在這裏插入圖片描述
在 window 中 合併兩個文件: type file1 >> file2
在這裏插入圖片描述
此時文件大小和 HDFS 系統上的文件大小一致, 修改名字成hadoop-2.7.2.tar.gz後解壓後查看
在這裏插入圖片描述

二、 HDFS 寫數據流程

2.1 剖析文件寫入

HDFS 寫數據流程
文件寫入過程

  1. 客戶端通過 Distributed FileSystem 向 NameNode 請求上傳文件, NameNode 檢查目標文件是否已存在, 父目錄是否存在;
  2. 如果不存在, NameNode 返回可以上傳; 如果已經存在, NameNode 返回不可以上傳;
  3. 客戶端請求上傳第一塊數據, 詢問 NameNode可以上傳到哪些DataNode 服務器上;
  4. NameNode 返回 3個 DateNode 節點, 分別爲 dn1, dn2, dn3;
  5. 客戶端通過 FSDateOutputStream模塊請求 dn1 上傳數據, dn1 收到請求會繼續調用 dn2, 然後 dn2 調用 dn3, 將這個通信管道建立完成;
  6. dn1、dn2、dn3 逐級應答客戶端;
  7. 客戶端開始往dn1上傳第一個Block(先從磁盤讀取數據放到一個本地內存緩存),以Packet爲單位,dn1收到一個Packet就會傳給dn2,dn2傳給dn3;dn1每傳一個packet會放入一個應答隊列等待應答。
  8. 當一個Block傳輸完成之後,客戶端再次請求NameNode上傳第二個Block的服務器。(重複執行3-7步)。

2.2 網絡拓撲-節點距離計算

在HDFS寫數據的過程中,NameNode會選擇距離待上傳數據最近距離的DataNode接收數據。那麼這個最近距離怎麼計算呢?

節點距離:兩個節點到達最近的共同祖先的距離總和。

下圖中機架中的每個節點相當於一臺服務器,

例如,假設有數據中心d1機架r1中的節點n1。該節點可以表示爲/d1/r1/n1。利用這種標記,這裏給出四種距離描述,如下圖所示。
在這裏插入圖片描述
在這裏插入圖片描述

2.3 機架感知(副本存儲節點選擇)

  1. 機架感知說明

    For the common case, when the replication factor is three, HDFS’s placement policy is to put one replica on one node in the local rack, another on a different node in the local rack, and the last on a different node in a different rack.

  2. Hadoop 副本節點選擇
    在這裏插入圖片描述
    思考: 爲什麼要這麼存?

三、 HDFS 讀數據流程

在這裏插入圖片描述

  1. 客戶端通過Distributed FileSystem向NameNode請求下載文件,NameNode通過查詢元數據,找到文件塊所在的DataNode地址。
  2. 挑選一臺DataNode(就近原則,然後隨機)服務器,請求讀取數據。
  3. DataNode開始傳輸數據給客戶端(從磁盤裏面讀取數據輸入流,以Packet爲單位來做校驗)。
  4. 客戶端以Packet爲單位接收,先在本地緩存,然後寫入目標文件。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章