Hadoop自带的存取小文件存取解决方案

2019-03-28 13:14|来源: 网络

现实场景;在系统中,存在大量的小文件存取,比如图片文件,一般在几M以内,

1),但是HDFS默认block大小是64M,如果直接存取在Hadoop中,将极大的消耗namenode的资源。直接放在hadoop文件系统中,大多只是做归档分析用,所以,我们就想能不能定期归档。

2),放在HBase中,由于Hbase的value最大长度是64KB,而很多小文件又大过这个级别。HBase当时的设计是为了存储网页元素这样的小数据,顶多几K,如果存储1M左右的小文件,还是不合适的。

对于小文件问题,Hadoop本身也提供了几个解决方案,分别为:Hadoop Archive,Sequence file和CombineFileInputFormat。

(1) Hadoop Archive

hadoop Archive或者HAR,是一个高效地将小文件放入HDFS块中的文件存档工具,它能够将多个小文件打包成一个HAR文件,这样在减少namenode内存使用的同时,仍然允许对文件进行透明的访问。

使用HAR时需要两点,第一,对小文件进行存档后,原文件并不会自动被删除,需要用户自己删除;第二,创建HAR文件的过程实际上是在运行一个mapreduce作业,因而需要有一个hadoop集群运行此命令。

该方案需人工进行维护,适用管理人员的操作,而且har文件一旦创建,Archives便不可改变,不能应用于多用户的互联网操作。

(2) Sequence file

sequence file由一系列的二进制key/value组成,如果为key小文件名,value为文件内容,则可以将大批小文件合并成一个大文件。

Hadoop-0.21.0中提供了SequenceFile,包括Writer,Reader和SequenceFileSorter类进行写,读和排序操作。

该方案对于小文件的存取都比较自由,不限制用户和文件的多少,但是SequenceFile文件不能追加写入,适用于一次性写入大量小文件的操作。

(3)CombineFileInputFormat

CombineFileInputFormat是一种新的inputformat,用于将多个文件合并成一个单独的split,另外,它会考虑数据的存储位置。

相关问答

更多
  • 分类: Java体系 在Jedis开发中,我们很多时候希望直接把一个对象放到Redis中,然后在需要的时候取出来。Redis的key和value都支持二进制安全的字符串,存储Java对象不是问题,下面我们看一下如何来实现。1要存储的对象 现在写一个很土的Java Bean,包含两个字段,id和name,类名叫做Person。为了实现序列化需求,该类实现Serializable接口。publicclassPersonimplementsSerializable{privateint id;private St ...
  • php文件的编码格式: header("charset=utf-8"); 在存储前,先把存储的字符串转码。 $string = iconv('UTF-8','GBK',$string); 这时候存储在redis中的中文就是GBK字符集的,读取的时候不是乱码了。 原理是window大部分系统上支持GBK字符集。
  • 学习了,以前用file_get_contents老是出错,原来要用二进制读
  • 首先创建测试表testtable CREATE TABLE testtable ( id INT(5) NOT NULL AUTO_INCREMENT PRIMARY KEY,filename CHAR(255),data LONGBLOB ); 将文件存入表中 mysql_connect( "localhost", "root", "password"); //连接数据库 mysql_select_db( "database"); //选定数据库 $filename="" //这里填入二进制文件名 $da ...
  • 你是用什么做的,vb??? 那你取的时候 用Format(rs("时间字段"),"yyyy-MM-dd HH-nn-ss") jsp啊,那你就在你的读取页面上 import java.text.SimpleDateFormat; 调用的时候 SimpleDateFormat f=newSimpleDateFormat("yyyy-MM-dd HH-nn-ss"); String str=f.format(你的日期变量); 输出就可以。 建议还是用当然是date了。你的参数类型尽量和你的库匹配,这样操起起来比 ...
  • json是一个固定格式的字符串, 其中只有数字和字符串、数组、对象几种种格式,字符串要用双引号括起来 分为数组和对象2种表示形式,数组是用[]括起来的,每个元素间用逗号隔开,获取元素跟java一样使用下标获取; 对象是用{}括起来的,这个对象只有属性和值,格式为 key:value,key:value,key:value。。。,key相当于java对象中的属性名,value就是属性值 举例 ["a","dddd","tttt"]这是数组 {a:1,b:2,c:5} 这个是对象,获取用对象。key取值 复杂一 ...
  • 这不能被实现在现有的Hadoop。 时设置的目录中,文件中的目录信息被读入Hadoop的输入已被确定 房东当时就完成所有文件的MapReduce,Hadoop的还是会等待输入,但房东可以想像,你能不能给Hadoop的信号,让他停止运行
  • 如果你使用类似TextInputFormat东西,问题是每个文件至少有一个分割,所以地图数量的上限是文件的数量,在你的情况下,你将有很多非常小的文件结束许多映射器处理每个非常少的数据。 为了解决这个问题,你应该使用CombineFileInputFormat ,它可以将多个文件打包到同一个CombineFileInputFormat中(我认为最多可以限制块的大小),所以对于这种格式,映射器的数量将独立于文件的数量,它将取决于关于数据量。 您将不得不通过从CombineFileInputFormt扩展来创建自 ...
  • 如果文件都是相同的“架构”,那么就像CSV或JSON一样。 然后,欢迎您编写一个非常基本的Pig / Spark作业来读取整个文件夹的小文件,然后将其写回到其他地方,这很可能会根据HDFS块大小将所有文件合并为更大的文件。 您还提到了Hive,因此对小文件使用外部表,并使用CTAS查询创建一个单独的表,从而创建一个MapReduce作业,就像Pig一样。 IMO,如果可能的话,最佳解决方案是设置Hadoop的“上游”系统,它将较小的文件批处理为较大的文件,然后将它们转储到HDFS。 Apache NiFi是 ...
  • Hadoop实际上有一个故障注入框架。 看到这个 。 Hadoop actually has a fault injection framework. See this.