ProtocolBuffer和lzo技术Hadoop系统上的使用

转自: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: yewang@taobao.com clm971910@gmail.com
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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值