啟用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

  1. <property> 
  2.   <name>io.compression.codecs</name> 
  3.   <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> 
  4. </property> 
  5. <property> 
  6.   <name>io.compression.codec.lzo.class</name> 
  7.   <value>com.hadoop.compression.lzo.LzoCodec</value> 
  8. </property> 

使用lzo,lzop,gzip,bzip2壓縮作為io壓縮的編解碼器,並指定lzo的類

mapred-site.xml

  1. <property> 
  2.   <name>mapred.compress.map.output</name> 
  3.   <value>true</value> 
  4. </property> 
  5. <property> 
  6.   <name>mapred.map.output.compression.codec</name> 
  7.   <value>com.hadoop.compression.lzo.LzoCodec</value> 
  8. </property> 
  9. <property> 
  10.   <name>mapred.child.java.opts</name> 
  11.   <value>-Djava.library.path=/opt/hadoopgpl/native/Linux-amd64-64</value> 
  12. </property> 

map結果採用壓縮輸出,可以降低網路頻寬的使用,並指定map輸出所使用的lzo的類。以及指定編解碼器所在位置。

建立lzo索引:

  1. hadoop jar /opt/hadoopgpl/lib/hadoop-lzo.jar com.hadoop.compression.lzo.LzoIndexer /data/rawlog/your_log_file.lzo

在streaming中使用lzo:

  1. hadoop jar /usr/share/hadoop/contrib/streaming/hadoop-streaming-1.0.3.jar  
  2. -file map.py  
  3. -file red.py  
  4. -mapper map.py  
  5. -reducer red.py  
  6. -inputformat com.hadoop.mapred.DeprecatedLzoTextInputFormat  
  7. -input /data/rawlog/test/20130325 -output /tmp/test_20130325

———————————————————-

以及在hive中指定壓縮編解碼器:

hadoop叢集啟用了壓縮,就需要在Hive建表的時候指定壓縮時所使用的編解碼器,否則Hive無法正確讀取資料。

Gzip和Bzip2由於是hadoop預設支援的,所以無需指定特殊的編解碼器,只要指定Text型別即可。

  1. CREATE EXTERNAL TABLE adpv_20130325( 
  2.   stat_date string,  
  3.   stat_hour string,  
  4.   ip string,  
  5.   logdate string,  
  6.   uid string,  
  7.   ver string,  
  8.   pid string,  
  9.   chid string,  
  10.   json string,  
  11.   country string,  
  12.   province string,  
  13.   city string,  
  14.   isp string) 
  15. ROW FORMAT DELIMITED  
  16.   FIELDS TERMINATED BY ` `  
  17. STORED AS TEXTFILE  
  18. LOCATION 
  19.   `hdfs://hadoopmaster:9000/data/dw/adpv/20130325` 

而LZO是外掛的第三方庫,所以要指定輸入和輸出的編解碼器。

  1. CREATE EXTERNAL TABLE adpv_20130325( 
  2.   stat_date string,  
  3.   stat_hour string,  
  4.   ip string,  
  5.   logdate string,  
  6.   uid string,  
  7.   ver string,  
  8.   pid string,  
  9.   chid string,  
  10.   json string,  
  11.   country string,  
  12.   province string,  
  13.   city string,  
  14.   isp string) 
  15. ROW FORMAT DELIMITED  
  16.   FIELDS TERMINATED BY ` `  
  17. STORED AS INPUTFORMAT  
  18.   `com.hadoop.mapred.DeprecatedLzoTextInputFormat`  
  19. OUTPUTFORMAT  
  20.   `org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat` 
  21. LOCATION 
  22.   `hdfs://hadoopmaster:9000/data/dw/adpv/20130325` 

至於你的日誌,就用lzop在本地壓縮好了,直接丟到hdfs上就可以了。

另外,在做資料清洗的時候,假如源日誌是lzo壓縮的,輸出的時候也希望使用lzo壓縮。則在資料清洗的指令碼中對hadoop的jobconf做一個指定。這樣就可以做到,輸入是lzo,輸出也可以lzo。或者輸入是text,輸出是lzo。

  1. -inputformat com.hadoop.mapred.DeprecatedLzoTextInputFormat -jobconf mapred.output.compress=true -jobconf mapred.output.compression.codec=com.hadoop.compression.lzo.LzopCodec 

最後對清洗過的日誌做Indexer就可以了,這樣無論是Hive還是做MR,都可以把大檔案分成多個map來平行計算。