轉自:http://www.searchtb.com/2010/09/pb-lzo-used-in-hadoop.html
概述
基於hadoop的集羣分佈式數據處理目前是淘寶搜索中心最重要的數據處理平臺,在集羣物理條件確定的情況下,有幾個方面影響了數據處理的速度。
1、數據大小 (影響磁盤IO和網絡IO)
2、數據格式 (影響數據的解析及構造速度)
3、並行度
使用 protocolBuffer + lzo技術,能幫我們做到數據小解析快並行度高這三點, 能幫我們大幅度提高處理的速度。下面詳細介紹一下如何編譯部署及開發相關代碼。
hadoop介紹
請參考 分佈式計算開源框架Hadoop介紹 和 官方網站http://hadoop.apache.org
protocolBuffer介紹
官方網站http://code.google.com/intl/zh-CN/apis/protocolbuffers/docs/overview.html
Google定義的一套數據協議,用於數據的結構化和序列化。 Google絕大部分模塊數據交互基於此數據協議。
1、平臺無關、語言無關。
2、二進制、數據自描述。
3、提供了完整詳細的操作API。
4、高性能 比xml要快20-100倍
5、尺寸小 比xml要小3-10倍 –高可擴展性
6、數據自描述、前後兼容
適用於
1、不同的平臺、系統、語言、模塊之間高效的數據交互
2、用於構建大型的複雜系統,降低數據層面的耦合度和複雜度
這裏要特別着重說的是protocolBuffer是一種數據協議,就像tcp/ip協議一樣,只要是遵守此協議的任何系統之間都能高效的進行數據交互。
第二個特別要說的是 數據自描述。 也就是說拿到任何一個protocolBuffer的數據文件,我們不需要任何其他的輔助信息,就能順利的解析出其中的數據信息。
這2點是最本質的。
google同時提供了一套代碼生成工具,能根據用戶自定義的.proto文件,生成c++/java/python的 代碼,用於調用protocolBuffer的內核API . 給我們使用提供了很大的便利
.proto文件 詳細請參考 官方網站
http://code.google.com/intl/zh-CN/apis/protocolbuffers/docs/overview.html
lzo介紹
LZO是一種高壓縮比和解壓速度極快的編碼, 特點是
解壓縮速度非常快。
LZO是無損壓縮,壓縮後的數據能準確還原
lzo是基於block分塊的,允許數據被分解成chunk,能夠被並行的解壓
下面說一下如何,部署編譯 hadoop protocolBuffer 和 lzo , 我下面提到的hadoop是基於 0.19.3版本的,需要很多額外的修改源碼的工作。 如果你使用的是 hadoop-0.20+ , 就省了這些麻煩的事情了, 可以不用修改代碼 直接編譯。
下面是一大堆的安裝編譯配置等的,這裏不轉了,有興趣的直接看原文吧。。。
運行使用
壓縮命令:
hadoop jar ~/hadoop_sta/hadoop/contrib/streaming/hadoop-0.19.2-dev-streaming.jar -input /app/aa.txt -output /test-lzo -mapper cat -reducer cat -jobconf mapred.output.compress=true -jobconf mapred.output.compression.codec=org.apache.hadoop.io.compress.LzoCodec
給lzo壓縮文件加索引:
hadoop jar /home/admin/hadoop_sta/hadoop/lib/hadoop-lzo-0.4.4.jar com.hadoop.compression.lzo.LzoIndexer /test-lzo/
給lzo文件加索引的目的是爲了讓lzo支持 splitable,這樣hadoop可以並行處理,
所以這一步很關鍵,生成的文件後綴 .index
我們在 hadoop-lzo-0.4.4.jar 另一個mapreduce版本的 創建索引的工具DistributedLzoIndexer
解壓命令:
hadoop jar ~/hadoop_sta/hadoop/contrib/streaming/hadoop-0.19.2-dev-streaming.jar
-inputformat org.apache.hadoop.mapred.LzoTextInputFormat
-input /test-lzo -output /test-txt -mapper cat -reducer cat
如何編寫 讀取 寫出 protocolBuffer + lzo 文件的mapreduce程序
編寫.proto文件
具體語法請參考protocolBuffer網站
例子:
<package com.taobao.proto;
message auction
{
optional string id = 1;
optional bytes title = 2;
optional string user = 3;
optional string pict_url = 4;
optional uint32 category = 5;
}
使用protoc程序生成java代碼
protoc –java_out=. auction.proto
生成的文件是 com/taobao/proto/Auction.java 文件
實現定製的inputFormat和outputFormat
主要是下面的3個類, 相關的代碼 在 我提供elephant-bird下載包的 taobao 目錄下都有
AuctionProtobufWritable.java
package com.taobao.proto.mapred.io;
import com.taobao.proto.Auction.auction;
import com.twitter.elephantbird.mapred.io.ProtobufWritable;
import com.twitter.elephantbird.util.TypeRef;
public class AuctionProtobufWritable extends ProtobufWritable<auction> {
public AuctionProtobufWritable() {
super(new TypeRef<auction>(){});
}
}
AuctionLzoProtobufBlockInputFormat.java
AuctionLzoProtobufBlockInputFormat.java
package com.taobao.proto.mapred.input;
import com.taobao.proto.Auction.auction;
import com.twitter.elephantbird.mapred.input.LzoProtobufBlockInputFormat;
import com.taobao.proto.mapred.io.AuctionProtobufWritable;
import com.twitter.elephantbird.util.TypeRef;
public class AuctionLzoProtobufBlockInputFormat extends LzoProtobufBlockInputFormat<auction, AuctionProtobufWritab
le>
{
public AuctionLzoProtobufBlockInputFormat()
{
setTypeRef(new TypeRef<auction>(){});
setProtobufWritable(new AuctionProtobufWritable());
}
}
AuctionLzoProtobufBlockOutputFormat.java
package com.taobao.proto.mapred.output;
import com.taobao.proto.Auction.auction;
import com.twitter.elephantbird.mapred.output.LzoProtobufBlockOutputFormat;
import com.taobao.proto.mapred.io.AuctionProtobufWritable;
import com.twitter.elephantbird.util.TypeRef;
public class AuctionLzoProtobufBlockOutputFormat extends LzoProtobufBlockOutputFormat<auction, AuctionProtobufWrit
able>
{
public AuctionLzoProtobufBlockOutputFormat()
{
setTypeRef(new TypeRef<auction>(){});
}
}
編寫mapreduce程序
job 的設置:
job.setOutputKeyClass(NullWritable.class);
job.setOutputValueClass(AuctionProtobufWritable.class);
job.setInputFormat(AuctionLzoProtobufBlockInputFormat.class);
job.setOutputFormat(AuctionLzoProtobufBlockOutputFormat.class);
mapper和reduce類:
import com.google.protobuf.ByteString;
import com.taobao.proto.Auction;
import com.taobao.proto.Auction.auction;
import com.taobao.proto.mapred.io.*;
import com.taobao.proto.mapred.input.*;
import com.taobao.proto.mapred.output.*;
public static class proto2protoMapper extends MapReduceBase implements Mapper<LongWritable, AuctionProtobufWrit
able, NullWritable, AuctionProtobufWritable>
{
@Override
public void map(LongWritable key, AuctionProtobufWritable value,
OutputCollector<NullWritable, AuctionProtobufWritable> outCollector, Reporter reporter)
throws IOException
{
auction pa = value.get();
auction.Builder builder = auction.newBuilder();
if (pa.hasId()) builder.setId(pa.getId());
if (pa.hasTitle()) builder.setTitle(pa.getTitle());
if (pa.hasUser()) builder.setUser(pa.getUser());
......
AuctionProtobufWritable pw = new AuctionProtobufWritable();
pw.set(builder.build());
outCollector.collect(NullWritable.get(), pw);
}
}
編譯成jar包
ant 編譯
如何運行
hadoop jar dist/taobao-proto-auction-1.0.jar com.taobao.proto.proto2proto /yewang/xml2proto /yewang/proto2proto
streaming調用方式,和map reduce處理程序 python樣例
編寫.proto文件
複用上面的 例子一樣
使用protoc 生成 python代碼
protoc –python_out=../python/ auction.proto
生成的文件是 auction_pb2.py
編寫map reduce 腳本
#!/home/admin/Python/bin/python
# -*- coding: utf-8 -*-
# Filename: reducer.py
# Author: [email protected] [email protected]
import auction_pb2
import sys
import base64
pa = auction_pb2.auction()
f = open("/dev/stdin", "rb")
while True:
line = f.readline();
if len(line) == 0:
break;
# 處理掉換行符 , (streaming.jar 幫我們加的)
line = line.strip();
# 切分出keyValue, (streaming.jar 幫我們加的)
keyValue = line.split("\t");
# base64 解碼
value = base64.standard_b64decode(keyValue[1]);
# 解析 成 proto 對象
pa.ParseFromString(value);
# 輸出部分內容, 需要帶上key, \t分隔,用於選擇合適的reducer
# print "1\t" + pa.title;
# 如果想要輸出proto , 需要將proto對象轉換成字符串, 然後base64編碼
print "1\t" + base64.standard_b64encode(value);
f.close()
如何運行
hadoop jar -libjars dist/taobao-proto-auction-1.0.jar /home/admin/hadoop_sta/hadoop/contrib/streaming/hadoop-0.19.2-dev-streaming.jar -input /yewang/testproto -output /yewang/testStreaming4 -file /home/admin/yewang/elephant-bird/taobao/src/python/auction_pb2.py -file /home/admin/yewang/elephant-bird/taobao/src/python/mapper.py -file /home/admin/yewang/elephant-bird/taobao/src/python/reducer.py -inputformat com.taobao.proto.mapred.input.AuctionLzoProtobufBlockB64InputFormat -outputformat com.taobao.proto.mapred.output.AuctionLzoProtobufBlockB64OutputFormat -reducer reducer.py -mapper mapper.py