啟用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 ` `
- 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 ` `
- 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來平行計算。