ProtoBuf的使用和原理

一、简介

  Protobuf是一个灵活的、高效的用于序列化数据的协议。相比较XML和JSON格式,protobuf更小、更快、更便捷。Protobuf是跨语言的,并且自带了一个编译器(protoc),只需要用它进行编译,可以编译成Java、python、C++等代码,然后就可以直接使用,不需要再写其他代码,自带有解析的代码。一条消息数据,用protobuf序列化后的大小是json的10分之一,xml格式的20分之一,是二进制序列化的10分之一。
 

二、安装

1、下载代码,https://github.com/google/protobuf
2、安装protobuf
tar -xzf protobuf-2.1.0.tar.gz
cd protobuf
./configure --prefix=/usr/local/protobuf
make
make check
make install

3、配置文件

1)vim /etc/profile 和 ~/.profile 中添加:
  export PATH=$PATH:/usr/local/protobuf/bin/
  export PKG_CONFIG_PATH=/usr/local/protobuf/lib/pkgconfig/
2)配置动态链接库,vim /etc/ld.so.conf,在文件中添加/usr/local/protobuf/lib(注意: 在新行处添加)
3)执行:ldconfig

三、类似技术对比

1、优点

  1)Protobuf同XML相比,主要优点在于性能高。它以高效的二进制方式存储,比XML小3到10倍,快20到100倍。
  2)可以自定义数据结构,然后使用代码生成器生成的代码来读写这个数据结构。你甚至可以在无需重新部署程序的情况下更新数据结构。只需使用 Protobuf 对数据结构进行一次描述,即可利用各种不同语言或从各种不同数据流中对你的结构化数据轻松读写。
  3)“向后”兼容性好,用户不必破坏已部署的、依靠“老”数据格式的程序就可以对数据结构进行升级。这样程序就可以不必担心因为消息结构的改变而造成的大规模的代码重构或者迁移的问题。因为添加新的消息中的 field 并不会引起已经发布的程序的任何改变。
  4)Protobuf语义更清晰,无需类似XML解析器的东西。Protobuf 编译器会将.proto文件编译生成对应的数据访问类以对Protobuf数据进行序列化、反序列化操作。
  5)使用 Protobuf 无需学习复杂的文档对象模型,Protobuf 的编程模式比较友好,简单易学,同时它拥有良好的文档和示例,对于喜欢简单事物的人们而言,Protobuf 比其他的技术更加有吸引力。
 

2、不足

  1)Protbuf 与 XML 相比也有不足之处。它功能简单,无法用来表示复杂的概念。
  2)XML 已经成为多种行业标准的编写工具,Protobuf 只是 Google 公司内部使用的工具,在通用性上还差很多。
  3)由于文本并不适合用来描述数据结构,所以 Protobuf 也不适合用来对基于文本的标记文档(如 HTML)建模。
  4)由于 XML 具有某种程度上的自解释性,它可以被人直接读取编辑,在这一点上 Protobuf 不行,它以二进制的方式存储,除非你有 .proto 定义,否则你没法直接读出 Protobuf 的任何内容。
 

3、举例对比

protobuf和xml存入数据:
//在XML中建模Person的name和email字段:
<person>
<name>John Doe</name>
<email>jdoe@example.com</email>
</person> //ProtocolBuffer的文本表示:
person {
name: "John Doe"
email: "jdoe@example.com"
}

读取数据:

//操作ProtocolBuffer也很简单:
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl; //而XML的你需要:
cout << "Name: " << person.getElementsByTagName("name")->item()->innerText() << endl;
cout << "E-mail: " << person.getElementsByTagName("email")->item()->innerText() << end;

四、使用场景

  1、需要和其它系统做消息交换的,对消息大小很敏感的,那么protobuf适合了,它语言无关,消息空间相对xml和json等节省很多。
  2、小数据的场合。如果你是大数据,用它并不适合。
  3、项目语言是c++,java,python的,因为它们可以使用google的源生类库,序列化和反序列化的效率非常高。其他语言需要第三方或者自己写,序列化和反序列化的效率不保证。
 
 

五、程序示例(C++版)

     该程序示例的大致功能是,定义一个Persion结构体和存放Persion的AddressBook,然后一个写程序向一个文件写入该结构体信息,另一个程序从文件中读出该信息并打印到输出中。
1、address.proto文件
package tutorial;

message Persion {
required string name = ;
required int32 age = ;
} message AddressBook {
repeated Persion persion = ;
}
编译.proto文件,执行命令: protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto,示例中执行命令protoc --cpp_out=/tmp addressbook.proto ,会在/tmp中生成文件addressbook.pb.h和addressbook.pb.cc。
 
2、write.cpp文件,向文件中写入AddressBook信息,该文件是二进制的
#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h" using namespace std; void PromptForAddress(tutorial::Persion *persion) {
cout << "Enter persion name:" << endl;
string name;
cin >> name;
persion->set_name(name); int age;
cin >> age;
persion->set_age(age);
} int main(int argc, char **argv) {
//GOOGLE_PROTOBUF_VERIFY_VERSION;
if (argc != ) {
cerr << "Usage: " << argv[] << " ADDRESS_BOOL_FILE" << endl;
return -;
}
tutorial::AddressBook address_book;
{
fstream input(argv[], ios::in | ios::binary);
if (!input) {
cout << argv[] << ": File not found. Creating a new file." << endl;
}
else if (!address_book.ParseFromIstream(&input)) {
cerr << "Filed to parse address book." << endl;
return -;
}
}
// Add an address
PromptForAddress(address_book.add_persion());
{
fstream output(argv[], ios::out | ios::trunc | ios::binary);
if (!address_book.SerializeToOstream(&output)) {
cerr << "Failed to write address book." << endl;
return -;
}
}
// Optional: Delete all global objects allocated by libprotobuf.
//google::protobuf::ShutdownProtobufLibrary(); return ;
}
编译write.cpp文件,执行命令:g++ addressbook.pb.cc write.cpp -o write `pkg-config --cflags --libs protobuf` ,注意,这里的`符号在键盘数字1键左边,也就是和~是同一个按键。
 
3、read.cpp文件,从文件中读出AddressBook信息并打印
#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h" using namespace std; void ListPeople(const tutorial::AddressBook& address_book) {
for (int i = ; i < address_book.persion_size(); i++) {
const tutorial::Persion& persion = address_book.persion(i); cout << persion.name() << " " << persion.age() << endl;
}
} int main(int argc, char **argv) {
//GOOGLE_PROTOBUF_VERIFY_VERSION; if (argc != ) {
cerr << "Usage: " << argv[] << " ADDRESS_BOOL_FILE" << endl;
return -;
} tutorial::AddressBook address_book; {
fstream input(argv[], ios::in | ios::binary);
if (!address_book.ParseFromIstream(&input)) {
cerr << "Filed to parse address book." << endl;
return -;
}
input.close();
} ListPeople(address_book); // Optional: Delete all global objects allocated by libprotobuf.
//google::protobuf::ShutdownProtobufLibrary(); return ;
}
编译read.cpp文件,g++ addressbook.pb.cc read.cpp -o read `pkg-config --cflags --libs protobuf`
 
4、执行程序结果
 
 
ref:
http://www.cnblogs.com/luoxn28/p/5303517.html
http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/index.html#resources
 
 
 

大数据 --> ProtoBuf的使用和原理的更多相关文章

  1. 大数据系列之数据仓库Hive原理

    Hive系列博文,持续更新~~~ 大数据系列之数据仓库Hive原理 大数据系列之数据仓库Hive安装 大数据系列之数据仓库Hive中分区Partition如何使用 大数据系列之数据仓库Hive命令使用 ...

  2. 【转】五分钟读懂大数据核心MapReduce架构及原理

    什么是MapReduce Hadoop中的MapReduce是一个简单的软件框架,基于它写出的应用程序可以运行在由上千个商用机器组成的大型集群上,并以一种可靠容错式并行处理TB级数据 MapReduc ...

  3. 大数据体系概览Spark、Spark核心原理、架构原理、Spark特点

    大数据体系概览Spark.Spark核心原理.架构原理.Spark特点 大数据体系概览(Spark的地位) 什么是Spark? Spark整体架构 Spark的特点 Spark核心原理 Spark架构 ...

  4. 大数据系列之数据仓库Hive安装

    Hive系列博文,持续更新~~~ 大数据系列之数据仓库Hive原理 大数据系列之数据仓库Hive安装 大数据系列之数据仓库Hive中分区Partition如何使用 大数据系列之数据仓库Hive命令使用 ...

  5. 大数据系列之数据仓库Hive命令使用及JDBC连接

    Hive系列博文,持续更新~~~ 大数据系列之数据仓库Hive原理 大数据系列之数据仓库Hive安装 大数据系列之数据仓库Hive中分区Partition如何使用 大数据系列之数据仓库Hive命令使用 ...

  6. 大数据系列之数据仓库Hive中分区Partition如何使用

    Hive系列博文,持续更新~~~ 大数据系列之数据仓库Hive原理 大数据系列之数据仓库Hive安装 大数据系列之数据仓库Hive中分区Partition如何使用 大数据系列之数据仓库Hive命令使用 ...

  7. 大数据运算模型 MapReduce 原理

    大数据运算模型 MapReduce 原理 2016-01-24 杜亦舒 MapReduce 是一个大数据集合的并行运算模型,由google提出,现在流行的hadoop中也使用了MapReduce作为计 ...

  8. 大数据组件原理总结-Hadoop、Hbase、Kafka、Zookeeper、Spark

    Hadoop原理 分为HDFS与Yarn两个部分.HDFS有Namenode和Datanode两个部分.每个节点占用一个电脑.Datanode定时向Namenode发送心跳包,心跳包中包含Datano ...

  9. Atitit. BigConfirmTips 控件 大数据量提示确认控件的原理and总结O9

    Atitit. BigConfirmTips 控件 大数据量提示确认控件的原理and总结O9 1. 主要的涉及的技术 1 2. 主要的流程 1 3. 调用法new confirmO9t(); 1 4. ...

随机推荐

  1. gm8180:arm linux启动加载模块、运行程序

    1. init #!/bin/busybox ash#load modules mao 2013-02-16 14:12:48 echo "************************m ...

  2. freemarker.core.ParseException:Unexpected end of file reached

    1.错误原因 freemarker.core.ParseException:Unexpected end of file reached 2.错误原因 由于在宏定义中,运用组件时没有关闭标签,导致出错 ...

  3. gplots heatmap.2和ggplot2 geom_tile实现数据聚类和热图plot

    主要步骤 ggplot2 数据处理成矩阵形式,给行名列名 hclust聚类,改变矩阵行列顺序为聚类后的顺序 melt数据,处理成ggplot2能够直接处理的数据结构,并加上列名 ggplot_tile ...

  4. Qt keyPressEvent

    keyPressEvent是QWidget里面的函数,所以凡是继承自QWidget的类都可以通过实现这个函数来完成对按键事件的响应. 要让当前的widget能够响应按键事件,最先需要做的事情是,调用: ...

  5. DELL XPS 13 9350 装Win7系统(坑爹)

    0.记一次悲惨的装机记录 1.为什么这么难装呢? 因为这个NB本身是为Win10设计的,所以官网没有Win7驱动,系统设置各种不兼容 2.希望你能看到本文最后 因为你看到最后,你就不会给这个逗比装Wi ...

  6. TensorLayer官方中文文档1.7.4:API – 数据预处理

    所属分类:TensorLayer API - 数据预处理¶ 我们提供大量的数据增强及处理方法,使用 Numpy, Scipy, Threading 和 Queue. 不过,我们建议你直接使用 Tens ...

  7. 结合实例分析Android MVP的实现

    最近阅读项目的源码,发现项目中有MVP的痕迹,但是自己却不能很好地理解相关的代码实现逻辑.主要原因是自己对于MVP的理解过于概念话,还没有真正操作过.本文打算分析一个MVP的简单实例,帮助自己更好的理 ...

  8. 【BZOJ1010】【HNOI2008】玩具装箱(斜率优化,动态规划)

    [BZOJ1010][HNOI2008]玩具装箱 题面 题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一 ...

  9. 在不同环境下MD5加密相同字符串,密文不一样的问题

    这是昨天做一个接口对接时遇到的一个问题.下面是md5加密的算法 public static String md555(String plainText) throws UnsupportedEncod ...

  10. Redis进阶实践之十七 Redis协议的规范

    一.介绍            Redis客户端使用称为RESP(Redis的序列化协议)的协议与Redis服务器进行通信. 虽然协议是专门为Redis设计的,但它可以用于其他客户端 - 服务器软件项 ...