启用lzo压缩对于小规模集群还是很有用的,压缩比率大概能达到原始日志大小的1/3。同时解压缩速度也比较快,Hadoop原生是支持gzip和bzip2压缩的,这两种压缩虽然压缩比率比lzo更大,但是在做map reduce解压缩的时候,慢的不能忍,所以通常不会用gzip或者bzip2。相同数据量,gzip的mr速度大概是lzo的1.5-2倍,而bzip2是lzo的3-4倍。
不过lzo不比gzip和bzip2是linux系统原生支持的,需要下载软件包并安装。这里至少涉及三个软件包。lzo,lzop和hadoop-gpl-packaging。我们是使用hadoop-gpl-packaging,或者也可以使用一个叫kevinweil的包。
gpl-packaging的作用主要是对压缩的lzo文件创建索引,否则的话,无论你的压缩文件是否大于HDFS的block大小,都只会按默认启动2个map操作,这是我们不愿意看到的事情。
当然,要启用lzo,以下这些操作每个节点都是需要做的。
下载编译lzo和lzop,这个就configure,make,make install就行了。
然后 http://code.google.com/p/hadoop-gpl-packing/downloads/list 下载最新的rpm包,并安装,安装完成会创建/opt/hadoopgpl文件夹。
接下来是具体步骤:
1. 将/opt/hadoopgpl/lib下的所有文件复制到/usr/lib和/usr/lib64。
2. 将/opt/hadoopgpl/native下的所有文件复制到/usr/share/hadoop/native,如果是tar包安装的hadoop,就复制到$HADOOP_HOME/lib下。
理论上是不需要这步的,但是在使用过程中发现省略了会在mr的过程中报错,通常就是报找不到lzo的jar包。
然后开始设置hadoop:
core-site.xml
- <property>
- <name>io.compression.codecs</name>
- <value>org.apache.hadoop.io.compress.DefaultCodec,com.hadoop.compression.lzo.LzoCodec,com.hadoop.compression.lzo.LzopCodec,org.apache.hadoop.io.compress.GzipCodec,org.apache.hadoop.io.compress.BZip2Codec</value>
- </property>
- <property>
- <name>io.compression.codec.lzo.class</name>
- <value>com.hadoop.compression.lzo.LzoCodec</value>
- </property>
使用lzo,lzop,gzip,bzip2压缩作为io压缩的编解码器,并指定lzo的类
mapred-site.xml
- <property>
- <name>mapred.compress.map.output</name>
- <value>true</value>
- </property>
- <property>
- <name>mapred.map.output.compression.codec</name>
- <value>com.hadoop.compression.lzo.LzoCodec</value>
- </property>
- <property>
- <name>mapred.child.java.opts</name>
- <value>-Djava.library.path=/opt/hadoopgpl/native/Linux-amd64-64</value>
- </property>
map结果采用压缩输出,可以降低网络带宽的使用,并指定map输出所使用的lzo的类。以及指定编解码器所在位置。
创建lzo索引:
- hadoop jar /opt/hadoopgpl/lib/hadoop-lzo.jar com.hadoop.compression.lzo.LzoIndexer /data/rawlog/your_log_file.lzo
在streaming中使用lzo:
- hadoop jar /usr/share/hadoop/contrib/streaming/hadoop-streaming-1.0.3.jar \
- -file map.py \
- -file red.py \
- -mapper map.py \
- -reducer red.py \
- -inputformat com.hadoop.mapred.DeprecatedLzoTextInputFormat \
- -input /data/rawlog/test/20130325 -output /tmp/test_20130325
----------------------------------------------------------
以及在hive中指定压缩编解码器:
hadoop集群启用了压缩,就需要在Hive建表的时候指定压缩时所使用的编解码器,否则Hive无法正确读取数据。
Gzip和Bzip2由于是hadoop默认支持的,所以无需指定特殊的编解码器,只要指定Text类型即可。
- CREATE EXTERNAL TABLE adpv_20130325(
- stat_date string,
- stat_hour string,
- ip string,
- logdate string,
- uid string,
- ver string,
- pid string,
- chid string,
- json string,
- country string,
- province string,
- city string,
- isp string)
- ROW FORMAT DELIMITED
- FIELDS TERMINATED BY '\t'
- STORED AS TEXTFILE
- LOCATION
- 'hdfs://hadoopmaster:9000/data/dw/adpv/20130325'
而LZO是外挂的第三方库,所以要指定输入和输出的编解码器。
- CREATE EXTERNAL TABLE adpv_20130325(
- stat_date string,
- stat_hour string,
- ip string,
- logdate string,
- uid string,
- ver string,
- pid string,
- chid string,
- json string,
- country string,
- province string,
- city string,
- isp string)
- ROW FORMAT DELIMITED
- FIELDS TERMINATED BY '\t'
- STORED AS INPUTFORMAT
- 'com.hadoop.mapred.DeprecatedLzoTextInputFormat'
- OUTPUTFORMAT
- 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
- LOCATION
- 'hdfs://hadoopmaster:9000/data/dw/adpv/20130325'
至于你的日志,就用lzop在本地压缩好了,直接丢到hdfs上就可以了。
另外,在做数据清洗的时候,假如源日志是lzo压缩的,输出的时候也希望使用lzo压缩。则在数据清洗的脚本中对hadoop的jobconf做一个指定。这样就可以做到,输入是lzo,输出也可以lzo。或者输入是text,输出是lzo。
- -inputformat com.hadoop.mapred.DeprecatedLzoTextInputFormat -jobconf mapred.output.compress=true -jobconf mapred.output.compression.codec=com.hadoop.compression.lzo.LzopCodec
最后对清洗过的日志做Indexer就可以了,这样无论是Hive还是做MR,都可以把大文件分成多个map来并行计算。
原文地址:http://slaytanic.blog.51cto.com/2057708/1162287