分享

讨论:HDFS Block压缩处理分析

easthome001 发表于 2013-10-25 10:46:02 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 13 26728
目前,使用Hadoop做多的应用是数据分析,如:Web日志分析等,这些源数据通常都是文本格式,占用磁盘空间大和网络带宽高。而且,HDFS为提高数据安全性,会对原始数据做N个备份(默认是在HDFS上存储三份数据),因此如果能够将原始数据压缩后再上传到HDFS,将会节省大量的磁盘空间和网络带宽。
    当然,这也会给HDFS带来额外的开销,因为在读取HDFSk上的数据之前,需要先将数据解压。不过,这个代价是划得来的。首先,在存储和备份数据时,已经为HDFS节省了大量的开销。另外,HDFS的瓶颈主要在I/O,而不是CPU,而解压主要是增加CPU开销,所以对HDFS的影响会更小。
    实际上,在整个过程当中,压缩的开销从HDFS移动了HDFS客户端。但客户端通常是分散的,而且一般不会集中上传相对HDFS来说的海量数据,所以这个影响对HDFS客户端来说也是可以接受的。
    通过上述的分析,预计经过压缩处理后,系统的整体效益会有很大的提升,当然还需要实践去验证,这个验证的难度并不大,只需要对HDFS做少量修改即可。
对于很多人关心的有关文件操作的语义,如:seek操作等,采用这种方式没有任何影响,因为这些操作都是发生在解压之后,而解压之后就相当于上传block时没有压缩一样,所以所有的对文件的操作是不受影响的,一切对用户来说都是透明的。

已有(13)人评论

跳转到指定楼层
sq331335144 发表于 2013-10-25 10:46:02
64M的文件变为12M左右,你用的什么压缩算法,并不是所有的文件都能压缩这么多
回复

使用道具 举报

ruanhero 发表于 2013-10-25 10:46:02
回复 2# appletreer
就使用zip压缩,对文本文件平均可以达到这个。
回复

使用道具 举报

poptang4 发表于 2013-10-25 10:46:02
回复 1# hadoopor
这个想法不错,但不用修改Hadoop源码也能达到。MR默认就支持在读取压缩文件时自动根据文件后缀名来解压压缩文件。
但是压缩格式的选择也是有考究的,并不是那种压缩级别高就用哪个,因为:
并不是所有压缩格式都是splittable的,比如gzip,而如果压缩文件不能被splitted,你就会失去locality的特性,使得你的MR程序变得低效。
举个例子:
假设HDFS的Block大小为64MB,一个已压缩的文件大小为1G文件,把它存在HDFS里,那么HDFS就会把它划分成16个Block。按平常来说,执行MR程序时每个Map task都会分到一个Block的数据,最终有16个Map tasks执行作业;但是由于这种压缩格式的文件不支持从任意点开始解压并读取数据,使得你只能把所有数据都归给一个Map task去处理,它必须得通过网络把存在其他nodes上的对应Blocks拷贝过来,然后再解压进行数据处理,这样的话,效率那将是十分低下的。
回复

使用道具 举报

a2325145 发表于 2013-10-25 10:46:02
本帖最后由 hadoopor 于 2009-11-25 12:58 编辑
回复 4# spork
    这个应当是HDFS层面要做的事,而不是MapReduce,简单点就是对一个block作为整个压缩块,对调用者来说,接口和形式不变,不需要感知数据是否进行过压缩。甚至可以考虑一个block由N个压缩块组成,一个原则是保证解压后方便一次性在内存中完成操作,所以不能太大,解压后64M是比较合理的。        另外,在上传文件到HDFS时,还可以对文件进行格式化处理,简单点使用TLV格式即可,这样在读取和处理数据时,就可以省去不少文本解析开销,当然完成这个的额外开销也丢给了客户端。
    每一个block对应一个Map任务,只需要保证一个压缩块不跨block即可,所以对任何内容都可以压缩,数据的分块由NameNode和DFSClient共同完成。当然可压缩比小的,再去压缩就有点多余,反而划不来了。
回复

使用道具 举报

oYaoXiang1 发表于 2013-10-25 10:46:02
回复 5# hadoopor
看你刚开始的貌似说的是把数据压缩后再上传到HDFS,然后由MR等进行处理。再看后面说的,你的意思是,压缩是HDFS内部做的。数据进到HDFS后,HDFS内部自动进行Block级别的压缩(或其它处理),外部Client调用时又自动解压缩然后返回给Client,我理解对吗?
照上面这样的话,在大集群中,replica数比较大的时候,那当上传大数据量时,集群的负荷就大了。
如果上传的文件已被压缩过,再压缩一次吗?关了吧,其它没压缩的还是继续占空间。
假设一个Block64MB,那怎么知道要多大的数据压缩后刚好能放到64MB里去,不行的话,跨Block了就会遇到上面我说的。
当然还有其它的,所以要想做这个有不少挑战和东西要斟酌的,我想做HDFS的人应该是考虑过的,可能做成特定于某些类型的数据存储会好一些。
回复

使用道具 举报

a2325145 发表于 2013-10-25 10:46:02
本帖最后由 hadoopor 于 2009-11-25 15:10 编辑
回复 6# spork
sorry没讲清楚。我的意思是客户端在提交数据之前,先将一个block压缩好后,才将这个block上传到HDFS,HDFS收到block后不会再对这个block进行压缩。不是对整个文件进行压缩,只以block为压缩单位,这和HTTP协议中的Transfer-Encoding类似,整个文件由若干压缩后的chunk组成。
回复

使用道具 举报

lxs_huntingjob 发表于 2013-10-25 10:46:02
噢,大概明白了。
以Block大小为压缩单元对原始数据分块,再把块分别压缩,然后再上传到HDFS。这样的话,Blocks之间不存在解压依赖关系,可以自由解压。
那压出来的Block大小应该是小于HDFS的Block大小咯吗?空间利用不足,虽然只是虚拟的Block空间。
那压完后是一个个Block往HDFS丢吗?映射关系怎么解决吗?必须得用特殊方法告诉HDFS这里几个Block是一起的,这样貌似是Client来管Blocks了,呵呵。或根本不管吗?
如果没映射,那Client调用时,咋调用相应的Block吗?还是每一个压完后的Block有自己的名字吗?就相当于把一个文件分成几个压缩过后的文件再丢进HDFS里吗?
呵呵,又一堆疑问,不知这次理解对没吗?
回复

使用道具 举报

oYaoXiang1 发表于 2013-10-25 10:46:02
回复 8# spork
映射关系不会变,和原来完全一样,只不过在读取数据之前,需要先解压罢了,但因为块不大,所以完全可快速在内存中直接解压,整个过程中就多了这个解压的开销。另外,空间利用不足的是不存在的,反而是节省了大量的空间,HDFS的block本来就对应一个物理文件,只不过现在这个文件变小了,理所当然的可以存储更多block了。还可以加上块头,内容包括块的大小和所采用的压缩算法等。
回复

使用道具 举报

leo_1989 发表于 2013-10-25 10:46:02
回复 9# hadoopor
把文件分块,分块压,再分块传,但是不要在HDFS端压缩,这个开销必须丢给CLIENT,依赖关系和原来一样,对NN来说,完全是透明的,它不需要关心,NN它不参与这个过程,元数据和原来一样,当然可以将压缩前的大小和压缩后的大小都告诉NN,不过也可以只告诉压缩前的大小。对HDFS本身来说,只是在读取数据时,多了一个解压过程。
回复

使用道具 举报

12下一页
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条