HDFS 07 - HDFS 性能調優之 合併小文件

1 - 爲什麼要合併小文件

HDFS 擅長存儲大文件

我們知道,HDFS 中,每個文件都有各自的元數據信息,如果 HDFS 中有大量的小文件,就會導致元數據爆炸,集羣管理的元數據的內存壓力會非常大。

所以在項目中,把小文件合併成大文件,是一種很有用也很常見的優化方法。

2 - 合併本地的小文件,上傳到 HDFS

將本地的多個小文件,上傳到 HDFS,可以通過 HDFS 客戶端的 appendToFile 命令對小文件進行合併。

在本地準備2個小文件:

# user1.txt 內容如下:
1,tom,male,16
2,jerry,male,10

# user2.txt 內容如下:
101,jack,male,19
102,rose,female,18

合併方式:

hdfs dfs -appendToFile user1.txt user2.txt /test/upload/merged_user.txt

合併後的文件內容:

3 - 合併 HDFS 的小文件,下載到本地

可以通過 HDFS 客戶端的 getmerge 命令,將很多小文件合併成一個大文件,然後下載到本地。

# 先上傳小文件到 HDFS:
hdfs dfs -put user1.txt user2.txt /test/upload
# 下載,同時合併:
hdfs dfs -getmerge /test/upload/user*.txt ./merged_user.txt

下載、合併後的文件內容:

4 - 通過 Java API 實現文件合併和上傳

代碼如下(具體測試項目,可到 我的 GitHub 查看):

@Test
public void testMergeFile() throws Exception {
    // 獲取分佈式文件系統
    FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop:9000"), new Configuration(), "healchow");
    FSDataOutputStream outputStream = fileSystem.create(new Path("/test/upload/merged_by_java.txt"));
    // 獲取本地文件系統
    LocalFileSystem local = FileSystem.getLocal(new Configuration());
    // 通過本地文件系統獲取文件列表,這裏必須指定路徑
    FileStatus[] fileStatuses = local.listStatus(new Path("file:/Users/healchow/bigdata/test"));
    for (FileStatus fileStatus : fileStatuses) {
        // 創建輸入流,操作完即關閉
        if (fileStatus.getPath().getName().contains("user")) {
            FSDataInputStream inputStream = local.open(fileStatus.getPath());
            IOUtils.copy(inputStream, outputStream);
            IOUtils.closeQuietly(inputStream);
        }
    }

    // 關閉輸出流和文件系統
    IOUtils.closeQuietly(outputStream);
    local.close();
    fileSystem.close();
}

合併的結果,和通過命令合併的完全一致:



版權聲明

作者:瘦風(https://healchow.com)

出處:博客園-瘦風的南牆(https://www.cnblogs.com/shoufeng)

感謝閱讀,公衆號 「瘦風的南牆」 ,手機端閱讀更佳,還有其他福利和心得輸出,歡迎掃碼關注🤝

本文版權歸博主所有,歡迎轉載,但 [必須在頁面明顯位置標明原文鏈接],否則博主保留追究相關人士法律責任的權利。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章