HDFS上不适合存储小文件,因为如果有很多的小文件,上传到HDFS集群,每个文件都会对应一个block块,一个block块的大小默认是128M,对于很多的小文件来说占用了非常多的block数量,就会影响到内存的消耗,
MapReduce处理这些文件的话也是需要很多的Map来处理.
HDFS提供的小文件的解决方案可以使用SequenceFile和MapFile:
如果存在大量的小数据文件,可以使用SequenceFile.
同时使用SequenceFile还可以用SequenceFile自带的一些压缩算法来减少这些细小文件的占用空间.
1.使用SequenceFile相关代码把本地Windows上的很多小文件上传到HDFS集群.
1 package seq;
2
3 import java.io.File;
4 import java.net.URI;
5
6 import org.apache.commons.io.FileUtils;
7 import org.apache.hadoop.conf.Configuration;
8 import org.apache.hadoop.fs.FileSystem;
9 import org.apache.hadoop.fs.Path;
10 import org.apache.hadoop.io.BytesWritable;
11 import org.apache.hadoop.io.SequenceFile;
12 import org.apache.hadoop.io.Text;
13
14 public class Test2 {
15 public static void main(String[] args) throws Exception {
16 Configuration conf = new Configuration();
17 org.apache.hadoop.fs.FileSystem fs = FileSystem.newInstance(new URI("hdfs://crxy99:9000"),conf);
18 Path out = new Path("/members.seq");//输出到HDFS的根目录下"/" 文件命名为memebers.seq
19 SequenceFile.Writer writer = new SequenceFile.Writer(fs, conf, out, Text.class, BytesWritable.class);//文件名作为key 类型是Text 文件内容作为值上传上去,类型是BytesWritable
20
21 File localDir = new File("F:\\360Downloads\\crxy\\video\\2016-05-10【mapreduce】 - 副本\\members2000");
22 for (File file : localDir.listFiles()) {
23 Text key = new Text(file.getName());
24 BytesWritable val = new BytesWritable(FileUtils.readFileToByteArray(file));
25 writer.append(key, val);
26 System.out.println(file.getName());
27 }
28 writer.close();
29 }
30 }
程序运行之后查看HDFS目录:
![]()
通过Web浏览HDFS集群可以看到members.seq文件的大小是126.54MB....只占用一个block.
上传的是一个在Windows本地的members的文件. Windows本地用户是ABC.
2.使用SequenceFile的block和record压缩算法进行上传文件的相关代码:
1 import java.io.File;
2 import java.net.URI;
3
4 import org.apache.commons.io.FileUtils;
5 import org.apache.hadoop.conf.Configuration;
6 import org.apache.hadoop.fs.FSDataOutputStream;
7 import org.apache.hadoop.fs.FileSystem;
8 import org.apache.hadoop.fs.Path;
9 import org.apache.hadoop.io.BytesWritable;
10 import org.apache.hadoop.io.IOUtils;
11 import org.apache.hadoop.io.SequenceFile;
12 import org.apache.hadoop.io.SequenceFile.CompressionType;
13 import org.apache.hadoop.io.Text;
14 import org.apache.hadoop.io.compress.GzipCodec;
15
16 public class Test1 {
17 public static void main(String[] args) throws Exception {
18 Configuration conf = new Configuration();
19 org.apache.hadoop.fs.FileSystem fs = FileSystem.newInstance(new URI("hdfs://crxy99:9000"),conf);
20 CompressionType type = null;
21 if("record".equals(args[0])){
22 type = CompressionType.RECORD;
23 }
24 if("block".equals(args[0])){
25 type = CompressionType.BLOCK;
26 }
27 FSDataOutputStream out = fs.create(new Path(args[1]));
28 SequenceFile.Writer writer = SequenceFile.createWriter(conf, out, Text.class, BytesWritable.class,type,new GzipCodec());
29
30 File localDir = new File("/usr/local/hadoop_repo/files/members2000");
31 for (File file : localDir.listFiles()) {
32 Text key = new Text(file.getName());
33 BytesWritable val = new BytesWritable(FileUtils.readFileToByteArray(file));
34 writer.append(key, val);
35 System.out.println(file.getName());
36 }
37 writer.close();
38 IOUtils.closeStream(out);
39 }
40 }
结果仍然如上图,文件占用的空间更小.
本文转自SummerChill博客园博客,原文链接:http://www.cnblogs.com/DreamDrive/p/5500112.html,如需转载请自行联系原作者