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)

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

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


免責聲明!

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



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