转自:http://www.searchtb.com/2010/09/pb-lzo-used-in-hadoop.html
基于hadoop的集群分布式数据处理目前是淘宝搜索中心最重要的数据处理平台,在集群物理条件确定的情况下,有几个方面影响了数据处理的速度。
1、数据大小 (影响磁盘IO和网络IO)
2、数据格式 (影响数据的解析及构造速度)
3、并行度
使用 protocolBuffer + lzo技术,能帮我们做到数据小解析快并行度高这三点, 能帮我们大幅度提高处理的速度。下面详细介绍一下如何编译部署及开发相关代码。
请参考 分布式计算开源框架Hadoop介绍 和 官方网站http://hadoop.apache.org
官方网站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是基于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
编写.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
编写.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