• Hadoop之小文件问题及解决方案


    Hadoop的HDFS和MapReduce都是针对大数据文件来设计的,在小文件的处理上不但效率低下,而且十分消耗内存资源
    针对HDFS而言,每一个小文件在namenode中都会占用150字节的内存空间,最终会导致集群中虽然存储了很多个文件,但是文件的体积并不大,这样就没有意义了。

    针对MapReduce而言,每一个小文件都是一个Block,都会产生一个InputSplit,最终每一个小文件都会产生一个map任务,这样会导致同时启动太多的Map任务,Map任务的启动是非常消耗性能的,但是启动了以后执行了很短时间就停止了,因为小文件的数据量太小了,这样就会造成任务执行消耗的时间还没有启动任务消耗的时间多,这样也会影响MapReduce执行的效率。

    针对这个问题,解决办法通常是选择一个容器,将这些小文件组织起来统一存储,HDFS提供了两种类型的容器,分别是SequenceFile 和 MapFile

    相对SequenceFile而言,MapFile的检索效率是高效的,缺点是会消耗一部分内存来存储index数据。

    一、SequenceFile解决方案:

    SequenceFile 写入:

    1. package hadoop.mr;
    2. import org.apache.commons.io.FileUtils;
    3. import org.apache.hadoop.conf.Configuration;
    4. import org.apache.hadoop.fs.FileSystem;
    5. import org.apache.hadoop.fs.FileUtil;
    6. import org.apache.hadoop.fs.Path;
    7. import org.apache.hadoop.io.SequenceFile;
    8. import org.apache.hadoop.io.Text;
    9. import java.io.File;
    10. import java.io.IOException;
    11. public class smallFileSeq {
    12. public static void main(String[] args) throws Exception{
    13. write("D:\\smallFile","/seqFile");
    14. }
    15. private static void write(String inputDir, String outputFile) throws Exception {
    16. Configuration conf = new Configuration();
    17. conf.set("fs.defaultFS", "hdfs://192.168.221.131:9000");
    18. try {
    19. FileSystem fileSystem = FileSystem.get(conf);
    20. fileSystem.delete(new Path(outputFile),true);
    21. } catch (IOException e) {
    22. e.printStackTrace();
    23. }
    24. //构造opts数组,有三个元素
    25. /*
    26. 第一个是输出路径
    27. 第二个是key类型
    28. 第三个是value类型
    29. */
    30. SequenceFile.Writer.Option[] opts = new SequenceFile.Writer.Option[]{
    31. SequenceFile.Writer.file(new Path(outputFile)),
    32. SequenceFile.Writer.keyClass(Text.class),
    33. SequenceFile.Writer.valueClass(Text.class)};
    34. //创建一个writer实例
    35. SequenceFile.Writer writer = SequenceFile.createWriter(conf, opts);
    36. File inputDirPath = new File(inputDir);
    37. if(inputDirPath.isDirectory()){
    38. File[] files = inputDirPath.listFiles();
    39. for(File file:files){
    40. String content= FileUtils.readFileToString(file,"UTF-8");
    41. Text key = new Text(file.getName());
    42. Text value = new Text(content);
    43. writer.append(key,value);
    44. }
    45. writer.close();
    46. }
    47. }
    48. }

    运行结果:

     SequenceFile 读取:

    1. public static void main(String[] args) throws Exception{
    2. read("/seqFile");
    3. }
    4. private static void write(String inputDir, String outputFile) throws Exception {
    5. Configuration conf = new Configuration();
    6. conf.set("fs.defaultFS", "hdfs://192.168.221.131:9000");
    7. try {
    8. FileSystem fileSystem = FileSystem.get(conf);
    9. fileSystem.delete(new Path(outputFile),true);
    10. } catch (IOException e) {
    11. e.printStackTrace();
    12. }
    13. private static void read(String inputFile) throws Exception{
    14. Configuration conf = new Configuration();
    15. conf.set("fs.defaultFS", "hdfs://192.168.221.131:9000");
    16. SequenceFile.Reader reader = new SequenceFile.Reader(conf, SequenceFile.Reader.file(new Path(inputFile)));
    17. Text key = new Text();
    18. Text value = new Text();
    19. while (reader.next(key,value)){
    20. System.out.print("文件名"+key.toString()+",");
    21. System.out.print("文件内容"+value.toString()+",");
    22. System.out.println("====");
    23. }
    24. reader.close();
    25. }

    运行结果:

     

    二、MapFile解决方案:

    MapFile写入:

    1. public static void main(String[] args) throws Exception{
    2. write("D:\\smallFile","/mapFile");
    3. }
    4. private static void write(String inputDir, String outputFile) throws Exception {
    5. Configuration conf = new Configuration();
    6. conf.set("fs.defaultFS", "hdfs://192.168.221.131:9000");
    7. try {
    8. FileSystem fileSystem = FileSystem.get(conf);
    9. fileSystem.delete(new Path(outputFile),true);
    10. } catch (IOException e) {
    11. e.printStackTrace();
    12. }
    13. SequenceFile.Writer.Option[] opts = new SequenceFile.Writer.Option[]{
    14. //SequenceFile.Writer.file(new Path(outputFile)),
    15. MapFile.Writer.keyClass(Text.class),
    16. MapFile.Writer.valueClass(Text.class)};
    17. MapFile.Writer writer = new MapFile.Writer(conf, new Path(outputFile),opts);
    18. File inputDirPath = new File(inputDir);
    19. if(inputDirPath.isDirectory()){
    20. File[] files = inputDirPath.listFiles();
    21. for(File file:files){
    22. String content= FileUtils.readFileToString(file,"UTF-8");
    23. Text key = new Text(file.getName());
    24. Text value = new Text(content);
    25. writer.append(key,value);
    26. }
    27. writer.close();
    28. }
    29. }

     MapFile读入:

    1. public class smallFileMapSeq {
    2. public static void main(String[] args) throws Exception{
    3. read("/mapFile");
    4. }
    5. private static void read(String inputFile) throws Exception{
    6. Configuration conf = new Configuration();
    7. conf.set("fs.defaultFS", "hdfs://192.168.221.131:9000");
    8. MapFile.Reader reader = new MapFile.Reader(new Path(inputFile),conf);
    9. Text key = new Text();
    10. Text value = new Text();
    11. while (reader.next(key,value)){
    12. System.out.print("文件名"+key.toString()+",");
    13. System.out.print("文件内容"+value.toString()+",");
    14. System.out.println("====");
    15. }
    16. reader.close();
    17. }
    18. }

  • 相关阅读:
    QT sqlite BLOB类型 写入数组
    SQL中的数据类型和规范化,助力数据存储优化
    LeetCode_滑动窗口_中等_395.至少有 K 个重复字符的最长子串
    C-Lodop打印文字超长自动缩小(文字按固定宽度缩放、js计算文本宽度)
    【vuex】
    软件测试Jenkins部署与配置
    黑客(网络安全)技术自学30天
    在用户同意隐私政策前,您的应用获取了用户的ANDROID ID,不符合华为应用市场审核标准。
    32GB Jetson Orin SOM 不能刷机问题排查
    【附源码】计算机毕业设计JAVA住房公积金筹集子系统的网站系统
  • 原文地址:https://blog.csdn.net/libaowen609/article/details/126323687