我們hadoop2,4集羣默認不支持snappy壓縮,但是最近有業務方說他們的部分數據是snappy壓縮的(這部分數據由另外一個集羣提供給他們時就是snappy壓縮格式的)想遷移到到我們集羣上面來進行計算,但是直接運行時報錯:
Failed with exception java.io.IOException:java.lang.RuntimeException:
native snappy library not available: this version of libhadoop was built without snappy support
根據報錯信息顯示snappy本地庫不可用,同時似乎在編譯libhadoop的時候需要特別指定以支持snappy,這一點不同於hadoop1.0,hadoop1.0只需要將snappy的本地庫文件往指定目錄一拷貝就行,不需要重新編譯libhadoop本地庫文件。
由於snappy壓縮算法壓縮比不是很高,雖然在解壓縮效率上又一點優勢,所以我們集羣默認沒有支持snappy,我們集羣的數據要求是RCFile+Gzip,以下是幾種壓縮格式在hadoop中的優缺點對比:
參考地址:http://www.linuxidc.com/Linux/2014-05/101230.htm
目前在Hadoop中用得比較多的有lzo,gzip,snappy,bzip2這4種壓縮格式,筆者根據實踐經驗介紹一下這4種壓縮格式的優缺點和應用場景,以便大家在實踐中根據實際情況選擇不同的壓縮格式。
1、gzip壓縮
優點:壓縮率比較高,而且壓縮/解壓速度也比較快;hadoop本身支持,在應用中處理gzip格式的文件就和直接處理文本一樣;有hadoop native庫;大部分linux系統都自帶gzip命令,使用方便。
缺點:不支持split。
應用場景:當每個文件壓縮之後在130M以內的(1個塊大小內),都可以考慮用gzip壓縮格式。譬如說一天或者一個小時的日誌壓縮成一個gzip文件,運行mapreduce程序的時候通過多個gzip文件達到併發。hive程序,streaming程序,和java寫的mapreduce程序完全和文本處理一樣,壓縮之後原來的程序不需要做任何修改。
2、lzo壓縮
優點:壓縮/解壓速度也比較快,合理的壓縮率;支持split,是hadoop中最流行的壓縮格式;支持hadoop native庫;可以在linux系統下安裝lzop命令,使用方便。
缺點:壓縮率比gzip要低一些;hadoop本身不支持,需要安裝;在應用中對lzo格式的文件需要做一些特殊處理(爲了支持split需要建索引,還需要指定inputformat爲lzo格式)。
應用場景:一個很大的文本文件,壓縮之後還大於200M以上的可以考慮,而且單個文件越大,lzo優點越越明顯。
3、snappy壓縮
優點:高速壓縮速度和合理的壓縮率;支持hadoop native庫。
缺點:不支持split;壓縮率比gzip要低;hadoop本身不支持,需要安裝;linux系統下沒有對應的命令。
應用場景:當mapreduce作業的map輸出的數據比較大的時候,作爲map到reduce的中間數據的壓縮格式;或者作爲一個mapreduce作業的輸出和另外一個mapreduce作業的輸入。
4、bzip2壓縮
優點:支持split;具有很高的壓縮率,比gzip壓縮率都高;hadoop本身支持,但不支持native;在linux系統下自帶bzip2命令,使用方便。
缺點:壓縮/解壓速度慢;不支持native。
應用場景:適合對速度要求不高,但需要較高的壓縮率的時候,可以作爲mapreduce作業的輸出格式;或者輸出之後的數據比較大,處理之後的數據需要壓縮存檔減少磁盤空間並且以後數據用得比較少的情況;或者對單個很大的文本文件想壓縮減少存儲空間,同時又需要支持split,而且兼容之前的應用程序(即應用程序不需要修改)的情況。
最後用一個表格比較上述4種壓縮格式的特徵(優缺點):
壓縮格式 | split | native | 壓縮率 | 速度 | 是否hadoop自帶 | linux命令 | 換成壓縮格式後,原來的應用程序是否要修改 |
---|---|---|---|---|---|---|---|
gzip | 否 | 是 | 很高 | 比較快 | 是,直接使用 | 有 | 和文本處理一樣,不需要修改 |
lzo | 是 | 是 | 比較高 | 很快 | 否,需要安裝 | 有 | 需要建索引,還需要指定輸入格式 |
snappy | 否 | 是 | 比較高 | 很快 | 否,需要安裝 | 沒有 | 和文本處理一樣,不需要修改 |
bzip2 | 是 | 否 | 最高 | 慢 | 是,直接使用 | 有 |
和文本處理一樣,不需要修改 |
綜上,我們hadoop2.4集羣要求RCFile+gzip是有一定道理的,首先RCFile格式的文件支持按列存儲,同時支持split,而gzip的壓縮率比較高,而且壓縮/解壓速度也比較快,所以RCFile格式的文件經過gzip壓縮後既能保證文件能split,還能保證很高壓縮/解壓速度和壓縮比。
以上說了半天題外話,以下來進入主題來說一下怎樣在不替換集羣本地庫文件,不重啓hadoop進程,也即在hadoop的客戶端就能解決支持snappy壓縮的問題的方法:
1、編譯snappy本地庫,編譯之後snappy本地庫文件地址:/data0/liangjun/snappy/
參考地址:http://www.tuicool.com/articles/yiiiY3R
2、重新編譯libhadoop.so文件,編譯時通過-Dsnappy.prefix指定snappy本地庫文件地址編譯:
mvn clean package -Pdist -Dtar -Pnative -Dsnappy.prefix=/data0/liangjun/snappy/ -DskipTests
注:我測試了一下,通過-Drequire.snappy編譯的libhadoop.so也是可行的:
mvn clean package -Pdist,native -DskipTests -Drequire.snappy
3、執行完上面兩步之後,最終只需要拿到libhadoop.so和libsnappy.so.1兩個文件(只需要這兩個文件,其他得經過我測試都過濾掉了),以下是MapReduce和hive的使用snappy壓縮的例子:
(1)、MapReduce,將編譯好的本地庫加到DistributedCache中就可以:
在測試環境的客戶端mapred-site.xml文件添加以下兩個配置項以支持map端數據的時候按snappy壓縮:
<property>
<name>mapreduce.map.output.compress</name>
<value>true</value>
<final>true</final>
</property>
<property>
<name>mapreduce.map.output.compress.codec</name>
<value>org.apache.hadoop.io.compress.SnappyCodec</value>
<final>true</final>
</property>
上傳libhadoop.so和libhadoop.so到指定hdfs目錄/test/snappy/下,通過-files指定文件:
hadoop jar hadoop-mapreduce-examples-2.4.0.jar wordcount -files hdfs://ns1/test/snappy/libhadoop.so,hdfs://ns1/test/snappy/libsnappy.so.1 /test/missdisk/ /test/wordcount
(2)、hive,通過add file指定文件:
hive >add file libhadoop.so;
hive >add file libsnappy.so.1;
hive >select count(*) from ct_tmp_objrec;
表ct_tmp_objrec的數據是文本文件經過snappy壓縮的數據,ct_tmp_objrec存儲格式是普通的文本格式。
運行hql之後,發現snappy格式的數據能夠正常處理計算了,但是200+M的文件只能由一個map任務處理,既不支持split。
==========================================================
以下部分是就RCFile+snappy的數據是否支持split的測試:
1、創建測試表snappy_test,該表和前面的ct_tmp_objrec列完全相同,只是hive表存儲格式換成了RCFile:
CREATE EXTERNAL TABLE `snappy_test`(
`from_id` string,
`to_id` string,
`mention_type` bigint,
`repost_flag` bigint,
`weight` double,
`confidence` double,
`from_uid` string,
`to_object_label` string,
`count` bigint,
`last_modified` string,
`time` string,
`mblog_spam` bigint,
`mblog_simhash` string,
`mblog_dupnum` bigint,
`mblog_attribute` bigint,
`user_quality` bigint,
`user_type` bigint,
`old_weight` double,
`obj_pos` bigint,
`quality` bigint)
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.columnar.LazyBinaryColumnarSerDe'
STORED AS INPUTFORMAT
'org.apache.hadoop.hive.ql.io.RCFileInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.RCFileOutputFormat'
LOCATION
'hdfs://ns1/user/liangjun/warehouse/tables/snappy_test'
2、將ct_tmp_objrec中plain text+snappy壓縮的數據轉成snappy_test中RCFile+gzip壓縮的數據:
hive >add file libhadoop.so;
hive >add file libsnappy.so.1;
hive >set hive.exec.compress.output=true;
hive >set mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;
hive >INSERT OVERWRITE table snappy_test select from_id,to_id,mention_type,repost_flag,weight,confidence,from_uid,to_object_label,count,last_modified,time,mblog_spam,mblog_simhash,mblog_dupnum,mblog_attribute,user_quality,user_type,old_weight,obj_pos,quality from ct_tmp_objrec;
3、查詢snappy_test中的RCFile+snappy數據看是否能split
hive >add file libhadoop.so;
hive >add file libsnappy.so.1;
hive >select count(*) from snappy_test;
運行hql之後,發現RCFile+snappy的數據能夠正常處理計算,同時200+M的文件split成兩個map任務處理,測試完成。參考地址:
http://blog.cloudera.com/blog/2011/09/snappy-and-hadoop/
http://blog.csdn.net/czw698/article/details/38387657
http://www.linuxidc.com/Linux/2014-05/101230.htmhttp://book.2cto.com/201305/21922.html
http://blog.csdn.net/czw698/article/details/38387657
http://blog.csdn.net/czw698/article/details/38398399
http://www.tuicool.com/articles/yiiiY3R