hadoop中支持的压缩方式有多种,比如Gzip,bzip2,zlib等,其中Gzip是hadoop中内置就支持的一种压缩方式,这种压缩方式在平 时linux 的开发人员和管理 员中使用的比较广泛,压缩比也比较高,压缩速度也还不 错,所以很多人都喜欢第一趋向于使用这种压缩格式进行文 件 的压缩。
在hadoop中,要在mapreduce 的job中使用gzip压缩是比较容易的,不记得是从哪个版本开始,hadoop就内置了使用gzip压缩格式读取输入文件,写中间结果和输出结果的支 持。
要在hadoop的mapreduce中使用gzip非常简单,分为以下几种情况:
- 从压缩的输入文 件时直接读入
由于hadoop在读取输入文件时,会很智能的根据输入文件的后缀名来进行判断是否采用压缩格式进行读入,所以当读到输入文件 是***.gz时,就会猜测该文件是一个用gzip压缩过的文件,于是就会尝试使用gzip的读取方式来读取. - 将mapreduce job所产生的中间结果进行压缩
由于mapreduce算法本身的特征,必然会在job的运行过程中产生一定的中间结果文件,当数据 量很大的时候,这些中间结果也非常的客观,一定程度上, 对job的效率会有一定的影响。由于通常计算任务的瓶颈都在磁盘的读写IO上,因此如果能够减少因中间文件而产生的disk IO,则对作业的效率肯定有益无害。因此如果希望将mapreduce作业的中间结果进行压缩,在hadoop的conf(可以通过修改hadoop- site.xml的配置选项,可以在程序中用JobConf的类接口设 置 ,或者在提交作业时用-D选项来设置该选项)中配置一个选项:
<property>
<name>mapred.compress.map.output</name>
<value>true</value>
</property>
这样,作业就会将产生的中间结果写 入slave local的时候,对结果进行压缩,reduce读取时也能够根据gz的后缀知道该中间结果是压缩文件,于是采用相应的读取格式来读取。 - 将 最终的计算输出的结果进行压缩
有的时候,我们需要对作业的运行结果进行历史保存,但是如果每天积累的计算结果非常大,又想要保存尽量多的历史结果 一边将来的结算,那么日积月累下,就会占据非常非常大的HDFS的存储空 间 ,并且由于是历史数据,使用的频率也不高,这就会造成很大的存储空间的浪费,因此,将计算的结果进行压缩,也是一种 非常好的节省空间的方法。要在hadoop job中做到这一点也很容易,只需要告诉hadoop,“我想要多job的输出结果进行压缩,并保存到HDFS上去”,就行了。具体的操作就是:在 conf中设置配置选项:
<property>
<name>mapred.output.compress</name>
<value>true</value>
</property>
以下是使用hadoop-0.19.1对一个11358 Byte的文件进行三种方式的压缩的对比:
- 读取非压缩文件,中间结果不 压缩,输出结果也不压缩
HDFS bytes read | HDFS bytes written | Local bytes read | Local bytes written | |
Map | 13872 | 0 | 0 | 9922 |
Reduce | 0 | 6117 | 9860 | 9860 |
Total | 13872 | 6117 | 9860 | 19782 |
- 读 取非压缩文件,中间结果压缩,输出结果不压缩
HDFS bytes read | HDFS bytes written | Local bytes read | Local bytes written | |
Map | 13872 | 0 | 0 | 9922 |
Reduce | 0 | 2663 | 9860 | 9860 |
Total | 13872 | 2663 | 9860 | 19782 |
- 读 取非压缩文件,中间结果压缩,输出结果也压缩
HDFS bytes raed | HDFS bytes written | Local bytes read | Local bytes written | |
Map | 13872 | 0 | 0 | 4221 |
Reduce | 0 | 2663 | 3623 | 3423 |
Total | 13872 | 2663 | 3623 | 7844 |
因此我们可以看到,在hadoop中使用gzip压缩来进行读取,中间结果,数据结果的保存都是非常的容易,因为hadoop native本身就提供了我们相应的类来解析和压缩数据。不过这里要特别提到的是:gzip压缩格式在hadoop中的支持有一定的局限性: 由于gzip压缩算法本身的原因,我们无法对gzip压缩文件进行分块,也就是说,在hadoop中,如果想要用hadoop 的mapreduce来处理数据,没一个mapper就必须对应一个gz文件,不能多个mapper对一个gzip文件的多个chunk进行并行的处理, 因此如果要在hadoop mapreduce任务中使用gzip,在数据处理之前就需要对数据进行认为的切分,让一个mapper来处理一块数据。这样其实有一点有违 mapreduce的本质。