百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

Google Protobuf vs. Apache Avro

liebian365 2024-10-24 14:38 48 浏览 0 评论



背景

序列化与反序列化是我们日常数据持久化和网络传输中经常使用的技术,但是目前各种序列化框架让人眼花缭乱,不清楚什么场景到底采用哪种序列化框架。本文会将选举支持跨语言、跨平台的Google Protobuf 和 Apache avro 两款进行对比。


Google protobuf

介绍

Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API。


特点

优点

  • 二进制消息,性能好/效率高(空间和时间效率都很不错)
  • proto文件生成目标代码,简单易用
  • 序列化反序列化直接对应程序中的数据类,不需要解析后在进行映射(XML,JSON都是这种方式)
  • 支持向前兼容(新加字段采用默认值)和向后兼容(忽略新加字段),简化升级
  • 支持多种语言(可以把proto文件看做IDL文件)
  • Netty等一些框架集成

缺点

  • 官方只支持C++,JAVA和Python语言绑定
  • 二进制可读性差(貌似提供了Text_Fromat功能)
  • 二进制不具有自描述特性
  • 默认不具备动态特性(可以通过动态定义生成消息类型或者动态编译支持)
  • 只涉及序列化和反序列化技术,不涉及RPC功能(类似XML或者JSON的解析器)


数据类型

ProtoBuf 有两个语言版本:v2 与 v3,需要在 *.proto 文件首行中明文标识 syntax="proto3",v3 与 v2 在语法上有一些区别例如:v3 去除了 optional、required 等,在语法上更为的简洁,我们这里主要介绍 v3,所以对 v2 就不做过多介绍了。protobuf属于轻量级的,因此不能支持太多的数据类型,下面是protobuf支持的基本类型列表并与c++类型对比,一般都能满足需求。N 表示打包的字节并不是固定。而是根据数据的大小或者长度。

protobuf 数据类型

描述

打包(字节)

C++语言映射

bool

布尔类型

1

bool

double

64位浮点数

N

double

float

32为浮点数

N

float

int32

32位整数、

N

int

uin32

无符号32位整数

N

unsigned int

int64

64位整数

N

__int64

uint64

64为无符号整

N

unsigned __int64

sint32

32位整数,处理负数效率更高

N

int32

sing64

64位整数 处理负数效率更高

N

__int64

fixed32

32位无符号整数

4

unsigned int32

fixed64

64位无符号整数

8

unsigned __int64

sfixed32

32位整数、能以更高的效率处理负数

4

unsigned int32

sfixed64

64为整数

8

unsigned __int64

string

只能处理 ASCII字符

N

std::string

bytes

用于处理多字节的语言字符、如中文

N

std::string

enum

可以包含一个用户自定义的枚举类型uint32

N(uint32)

enum

message

可以包含一个用户自定义的消息类型

N

object of class


特殊类型

类型

描述

enum类型

枚举用来表示一定范围内具有相同属性的值

map类型

一组k-v格式的数据集合

集合类型

使用repeated标示字段,被 repeated 标识的字段可以理解为是一个数组

自定义对象

使用message 在定义过程中是可以声明自己定义的 message 类型,Protocol Buffers 定义 message 允许嵌套组合成更加复杂的消息。

要使用使用protobuf,首先需要定义一个.proto格式的文件,格式类似下面这样

syntax="proto3";
package exmple; //每个 *.proto 文件可以指定 package 作为生成语言的 namespace

message Person {
    int64 id = 1;
    string name = 2;
    enum Skills {
        GOLANG = 0;
        PYTHON = 1;
        JAVA = 2;
        RUST = 3;
        CPP = 4;
    }
    repeated Skills skill = 3;  // 这里表示 skills 可以接受多个 string 类型的值
    map<string, hobby> hobbys = 4; //message 定义时可以使用 map 类型
}

message hobby{
    string hobby=1;
}


编码方面

protocol buffers 自带代码生成工具,可以生成友好的数据访问存储接口。从而开发人员使用它来编码更加方便。例如上面的例子,如果用 C++ 的方式去读取用户的名字和 email,直接调用对应的 get 方法即可(所有属性地get 和 set 方法的代码都自动生成好了,只需要调用即可),Protobuf 语义更清晰,无需类似 XML 解析器的东西(因为 Protobuf 编译器会将 .proto 文件编译生成对应的数据访问类以对 Protobuf 数据进行序列化、反序列化操作)。

使用 Protobuf 无需学习复杂的文档对象模型,Protobuf 的编程模式比较友好,简单易学,同时它拥有良好的文档和示例,对于喜欢简单事物的人们而言,Protobuf 比其他的技术更加有吸引力。protocol buffers 最后一个非常棒的特性是,即“向后”兼容性好,人们不必破坏已部署的、依靠“老”数据格式的程序就可以对数据结构进行升级。这样您的程序就可以不必担心因为消息结构的改变而造成的大规模的代码重构或者迁移的问题。因为添加新的消息中的 field 并不会引起已经发布的程序的任何改变(因为存储方式本来就是无序的,k-v 形式)。


Apache Avro

介绍

Avro是Hadoop中的一个子项目,也是Apache中一个独立的项目,Avro是一个基于二进制数据传输高性能的中间件。在Hadoop的其他项目中例如HBase(Ref)和Hive(Ref)的Client端与服务端的数据传输也采用了这个工具。Avro是一个数据序列化的系统。Avro 可以将数据结构或对象转化成便于存储或传输的格式。Avro设计之初就用来支持数据密集型应用,适合于远程或本地大规模数据的存储和交换


特点

优点

  • 二进制消息,性能好/效率高
  • 使用JSON描述模式
  • 模式和数据统一存储,消息自描述,不需要生成stub代码(支持生成IDL)
  • RPC调用在握手阶段交换模式定义
  • 包含完整的客户端/服务端堆栈,可快速实现RPC
  • 支持同步和异步通信
  • 支持动态消息
  • 模式定义允许定义数据的排序(序列化时会遵循这个顺序)
  • 提供了基于Jetty内核的服务基于Netty的服务

缺点

  • 只支持Avro自己的序列化格式
  • 语言绑定不丰富


数据类型

Apache avro 的 Schema 通过 JSON 对象表示也可以使用IDL。Schema 定义了简单数据类型和复杂数据类型,其中复杂数据类型包含不同属性。通过各种数据类型用户可以自定义丰富的数据结构。

基本类型有:

类型

说明

null

no value

boolean

a binary value

int

32-bit signed integer

long

64-bit signed integer

float

single precision (32-bit) IEEE 754 floating-point number

double

double precision (64-bit) IEEE 754 floating-point number

bytes

sequence of 8-bit unsigned bytes

string

unicode character sequence

Avro定义了六种复杂数据类型:

类型

说明

Record

任意类型的一个命名字段集合

Enum

枚举类型

Array

数组类型

Map

Map是一种定义keys和values列表的方法

Union

组合类型,表示各种类型的组合,使用数组进行组合

Fixed

fixed 类型,一组固定数量的8位无符号字节


要使用使用Apache avro ,首先需要定义一个Schema,格式类似下面这样

JSON格式:

{
    "namespace": "avro", #namespace是包名
    "type": "record",
    "name": "User", 
    "fields": [
        {"name": "name", "type": "string"},
        {"name": "id", "type": "int"},
        {"name": "salary", "type": "int"},
        {"name": "age", "type": "int"},
        {"name": "address", "type": "string"}
    ]
}
  • namespace:定义了根据 schema 文件生成的类的包名
  • type:固定写法
  • name:生成的类的名称
  • fields:定义了生成的类中的属性的名称和类型,其中"type": ["int", "null"]的意思是,favorite_number 这个属性是int类型,但可以为null

或者IDL格式:

record User {
    string  name;
    int id;
    int salary;
    int  age;
    string address;
}


编码方式

Avro支持两种序列化编码方式:二进制编码和JSON编码使用二进制编码会高效序列化,并且序列化后得到的结果会比较小;而JSON一般用于调试系统或是基于WEB的应用。对Avro数据序列化/反序列化时都需要对模式以深度优先(Depth-First),从左到右(Left-to-Right)的遍历顺序来执行。基本类型的序列化容易解决,混合类型的序列化会有很多不同规则。对于基本类型和混合类型的二进制编码在文档中规定,按照模式的解析顺序依次排列字节。对于JSON编码,联合类型(Union Type)就与其它混合类型表现不一致。 Avro为了便于MapReduce的处理定义了一种容器文件格式(Container File Format)。这样的文件中只能有一种模式,所有需要存入这个文件的对象都需要按照这种模式以二进制编码的形式写入。对象在文件中以块(Block)来组织,并且这些对象都是可以被压缩的。块和块之间会存在同步标记符(Synchronization Marker),以便MapReduce方便地切割文件用于处理


总结

Protobuf具有跨平台、解析速度快、序列化数据体积小、扩展性高、使用简单的特点,但是内嵌并没有提供RPC的通讯。Avro显式schema设计以及动态模式(不用生成代码,而且性能很好)使它更适用于搭建数据交换及存储的通用工具和平台,特别是在后台。

protobuf适合场景, 需要和其它系统做消息交换的,对消息大小很敏感的。那么protobuf适合了,它语言无关,消息空间相对xml和json等节省很多 小数据的场合。如果你是大数据,用它并不适合。 项目语言是c++,java,python的,因为它们可以使用google的源生类库,序列化和反序列化的效率非常高。其它的语言需要第三方或者自己写,序列化和反序列化的效率不保证。 总体而言,protobuf还是非常好用的,被很多开源系统用于数据通信的工具,在google也是核心的基础库。

Avro适合场景场景,avro与Hadoop生态系统结合最好,Hive表定义可以直接用avro schema来声明,Hive里用它来序列化日志文件,优点是可以直接用avro schema替代Hive本身表结构定义,这样能比较方便的解决schema evolution问题,在kafka和Flume 中也有很多使用avro的. flume主要的RPC source就是Avro source, 与 Avro sink, FlumeSDK等构成Flume内部通信。



Protobuf

avro

开源协议

BSD-style

Apache

schema

IDL

JSON ,也支持IDL

是否需要代码动态生成

需要

可选

是否动态生成rpc接口

是否生成rpc实现

相关推荐

4万多吨豪华游轮遇险 竟是因为这个原因……

(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...

“菜鸟黑客”必用兵器之“渗透测试篇二”

"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...

科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白

作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...

麦子陪你做作业(二):KEGG通路数据库的正确打开姿势

作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...

知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势

智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...

每日新闻播报(September 14)_每日新闻播报英文

AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...

香港新巴城巴开放实时到站数据 供科技界研发使用

中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...

5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper

本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...

Qt动画效果展示_qt显示图片

今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...

如何从0到1设计实现一门自己的脚本语言

作者:dong...

三年级语文上册 仿写句子 需要的直接下载打印吧

描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...

C++|那些一看就很简洁、优雅、经典的小代码段

目录0等概率随机洗牌:1大小写转换2字符串复制...

二年级上册语文必考句子仿写,家长打印,孩子照着练

二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...

一年级语文上 句子专项练习(可打印)

...

亲自上阵!C++ 大佬深度“剧透”:C++26 将如何在代码生成上对抗 Rust?

...

取消回复欢迎 发表评论: