ProtocolBuffer 结合 LZO在 Hadoop中的使用(三)

ProtocolBuffer 结合 LZO在 Hadoop中的使用(三)

1.自动生成Protocol buffer对象

1、把protoc.exe文件复制到 c:\windows 目录中(呵呵,这样最省事),window7放在windows/system32下

下载地址


2、使用 protocol buffer 编译器编译 logFormat.proto 文件。打开命令行窗口,并定位到logFormat.proto文件目录中,运行命令 protoc --java_out=. logFormat.proto(注意.后面有空格,否则会有错误),执行这个命令后会在当前目录下生成一个java类com.searchlog.LogFormat.java。

下载 protobuf-java-2.4.1.jar

//http://code.google.com/apis/protocolbuffers/docs/proto.html

option java_package = "com.searchlog";

message URI {
optional string protocol=1;
optional string host=2;
optional int32 port=3;
optional string path=4;
optional string query=5;
}


message SearchLog {
optional int64 id=39;
optional string remote_addr=1;
optional int64 time=2; //日志的时间,从1970年以来的毫秒值
optional int32 status=3;
optional int32 body_bytes_sent=4;
optional string ua=5;
optional string CookieId=6; //si. 标识唯一用户.
optional string lastVisitTime=7; //lt. 上次页面加载时间
optional string screenResolution=8; //sr. 屏幕分辨率
optional string language=33; //ln.浏览器语言
optional bool cookieEnabled=9; //ca. 是否启用cookie
optional bool javaEnable=10; //ja. 是否启用java
optional URI refer=11; //re. referer
optional URI location=12; //lo. 当前页面的location
optional string flashVersion=13; //fv.flashversion
optional string clickPoint=14;//cp. 页面上点击坐标
optional int32 rand=15; //rand. 随机字符串
optional string keyword=16; //k. 搜索keyword
optional int32 type=17; 
optional int32 pos=18;
optional string pageStay=42; //ps.页面停留时间
optional string jsVersion=20; //v. 统计代码版本
optional int32 sendCount=21;//c. 本页发送统计数据的次数
optional string uuid=22; //uuid. 页面唯一id表示
optional string timestamp=23; //ts
optional int32 ds=24; //ds. 页面直达区个数
optional int32 vs=25;//vs. 页面普通结果数
optional string pid=26; //pid. 点击链接的节目id
optional string vid=27; //vid. 点击链接的视频id
optional int32 pageno=28; //pn. 当前页码
optional int32 mc=29; //mc. 点击直达区更多,1点击展开,2点击隐藏
optional int32 ct=30; //ct. 直达区分类:
optional int32 directpos=31; //directpos
optional int32 origin=32; //0,tudou. 1,youku
optional string ok=34; //ok,用户在输入框中输入的词
optional string os=35; //os,用户通过kubox选择的词
optional int32 ki=37; //ki.用户选择的第几个提示词
optional string lastKeyword=38; //lk.上一次的搜索词
optional string kt=36; //kt. 
optional int32 sh=40; //sh. 是否屏蔽词。1,是。0或者不填,不是。
optional int32 site=41; 
};

这边介绍一下该文件定义的语法:

package com.searchlog.proto; // 声明包,表明此声明下方的数据结构都属于此包, package起到命名空间的作用避免变量命名冲突,使用protoc.exe编译.proto文件后,package名即转换为相应的命名空间;

 

定义在message A里边的message B在protoc.exe编译后,会成为package 下的两个平行的类:

 public static final class URI extends
      com.google.protobuf.GeneratedMessage
      implements URIOrBuilder {
...
}

 public static final class SearchLog extends
      com.google.protobuf.GeneratedMessage
      implements SearchLogOrBuilder{
...
}


message中的每一个成员都必须使用域规则(field rules)required、optional、repeated 三者之一作为前置声明。

required 修饰的成员必须被赋值,如果libprotobuf 在debug模式下编译,那么对包含未初始化的repeated成员的对象进行序列化的时候将会失败,如果libprotobuf经过优化编译,那么序列化会继续进行而不产生错误,但对序列化后的数据进行解析会失败。

对于optional 成员,其值可以不被初始化,但在可行的时候应为optional 成员设定默认值。如果没有默认值,那么系统会自动为optional成员添加默认值,对于数值类型,默认值是0;对于字符串类型,默认为空串;bool类型默认值为false。对于嵌套的message,其默认值为默认的对象或原型,即未初始化的对象。访问默认对象的成员得到的将是系统默认值。

repeated成员意味着可以包含多个此类型的成员(也可以是0个)。

 

对于message中的required 和optional 变量var,使用相应的set_var函数对成员变量赋值;对于repeated 变量 revar, 使用 add_revar 函数进行赋值。

 拿其中的一个字段来说:

生成的代码中含有:

// optional string lastVisitTime = 7;
      private java.lang.Object lastVisitTime_ = "";
      public boolean hasLastVisitTime() {
        return ((bitField0_ & 0x00000080) == 0x00000080);
      }
      public String getLastVisitTime() {
        java.lang.Object ref = lastVisitTime_;
        if (!(ref instanceof String)) {
          String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
          lastVisitTime_ = s;
          return s;
        } else {
          return (String) ref;
        }
      }
      public Builder setLastVisitTime(String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000080;
        lastVisitTime_ = value;
        onChanged();
        return this;
      }
      public Builder clearLastVisitTime() {
        bitField0_ = (bitField0_ & ~0x00000080);
        lastVisitTime_ = getDefaultInstance().getLastVisitTime();
        onChanged();
        return this;
      }
      void setLastVisitTime(com.google.protobuf.ByteString value) {
        bitField0_ |= 0x00000080;
        lastVisitTime_ = value;
        onChanged();
      }

使用的时候:


SearchLog.Builder builder = SearchLog.newBuilder()
builder.setLastVisitTime(value.get(0));
SearchLog msg = builder.build();



对于任意类型的成员var, 都可以通过 have_var() 来判断成员变量是否已经赋值;通过clear_var() 来清除变量内容;对于对象,可以通过 IsInitialized()函数判断required类型成员是否全部初始化;使用clear()清理对象的所有成员。对于repeated成员b,b_size()函数可以用来获取b成员的个数。

 

对于string成员S,使用mutable_S()函数将使得你得到直接指向该成员的指针(direct pointer),而无论该成员是否已经初始化。

 

message 成员的类型可以是基础类型boolint32floatdoublestring也可以是复杂的自定义类型,自定义类型可以嵌套。更详细的类型支持列表:http://code.google.com/apis/protocolbuffers/docs/proto.html



3.将生成的ProtoBufferPractice.java文件引入eclipse

4.把下载的protobuf-java-2.4.1.jar也引入工程

option java_package = “com.example.foo”;
我认为比较重要的文件级选项有
java_package ——指定生成的java代码的packge。
java_outer_classname ——protoc会为每个.proto文件一个java类,其中每个message都做作为该java类的内部类,这个选项就用于指定外围类的类名。
optimize_for ——用于优化protoc产生的代码,有三种模式:
SPEED –产生的代码将具有最好的序列化/反序列化执行速度。
CODE_SIZE –产生的代码将具有更少的代码行数。
LITE_RUNTIME –protocol buffer有一个简化版的runtime库,比如要生成用于手机平台的代码,可以使用这个选项。
另外,packed是一个字段级选项,在上面字段修改符repeated中提到了。



分析:
   个人认为pb之所以快和省流量除了本省字节少以外,序列化过程减少的字节数是主要因素
具体可参考
http://kangsg219.iteye.com/blog/904762

其他参考:http://www.searchtb.com/2010/11/protocol-buffers%E7%9A%84%E5%BA%94%E7%94%A8%E4%B8%8E%E5%88%86%E6%9E%90.html

在实践中具体选择什么还需要依情况而定:
http://www.oschina.net/question/12_10307



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LZO是一种高效的压缩算法,可以在Hadoop用于压缩和解压缩数据,从而提高数据处理的效率。下面是将LZO库安装到Hadoop的步骤: 1. 下载LZO 你可以从LZO的官方网站(http://www.oberhumer.com/opensource/lzo/)上下载LZO的源代码。 2. 安装LZO 解压下载的LZO源代码包,进入解压后的文件夹,执行以下命令进行编译和安装: ``` ./configure --prefix=/usr/local make sudo make install ``` 3. 下载Hadoop LZO库 从Hadoop官方网站(http://www.apache.org/dyn/closer.cgi/hadoop/common/)下载与你当前使用Hadoop版本相对应的LZO库。例如,如果你使用的是Hadoop 2.7.3版本,则应该下载hadoop-lzo-0.4.20.tar.gz。 4. 安装Hadoop LZO库 解压下载的Hadoop LZO库,进入解压后的文件夹,执行以下命令进行编译和安装: ``` export LZO_HOME=/usr/local export HADOOP_HOME=/path/to/your/hadoop export HADOOP_PREFIX=$HADOOP_HOME export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native export MAVEN_OPTS="-Xmx2g -XX:MaxPermSize=512M -XX:ReservedCodeCacheSize=512m" mvn clean package -Pdist,native -DskipTests=true -Dtar ``` 其,`/usr/local`应该替换为你之前安装LZO时指定的安装路径;`/path/to/your/hadoop`应该替换为你的Hadoop安装路径。 编译和安装完成后,将生成的`hadoop-lzo-0.4.20.tar.gz`文件解压到Hadoop的安装目录,并将其的`.jar`和`.so`文件复制到Hadoop的`lib`目录。 5. 配置Hadoop 编辑Hadoop的配置文件`$HADOOP_HOME/etc/hadoop/core-site.xml`,加入以下内容: ``` <property> <name>io.compression.codecs</name> <value>com.hadoop.compression.lzo.LzoCodec,com.hadoop.compression.lzo.LzopCodec</value> </property> <property> <name>io.compression.codec.lzo.class</name> <value>com.hadoop.compression.lzo.LzoCodec</value> </property> <property> <name>io.compression.codec.lzop.class</name> <value>com.hadoop.compression.lzo.LzopCodec</value> </property> <property> <name>mapreduce.map.output.compress</name> <value>true</value> </property> <property> <name>mapreduce.map.output.compress.codec</name> <value>com.hadoop.compression.lzo.LzoCodec</value> </property> ``` 其,`com.hadoop.compression.lzo`是LZO的Java包名。 6. 测试 在Hadoop使用LZO进行压缩和解压缩数据时,需要指定相应的压缩和解压缩类。例如,在MapReduce作业使用LZO进行压缩和解压缩数据时,可以使用以下命令: ``` hadoop jar your-jar-file.jar \ -D mapreduce.map.output.compress=true \ -D mapreduce.map.output.compress.codec=com.hadoop.compression.lzo.LzoCodec \ -D mapred.output.compress=true \ -D mapred.output.compression.codec=com.hadoop.compression.lzo.LzoCodec \ input-path \ output-path ``` 其,`com.hadoop.compression.lzo.LzoCodec`是LZO用于压缩和解压缩数据的类名。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值