AVRO格式学习总结

1. 介绍

Avro 是 Hadoop 中的一个子项目,也是 Apache 中一个独立的项目,Avro 是一个基于二进制数据传输高性能的中间件。在 Hadoop 的其他项目中,例如 HBase 和 Hive 的 Client 端与服务端的数据传输也采用了这个工具。Avro 是一个数据序列化的系统,它可以提供:

1、丰富的数据结构类型
    
    2、快速可压缩的二进制数据形式
    
    3、存储持久数据的文件容器
    
    4、远程过程调用 RPC
    
    5、简单的动态语言结合功能,Avro和动态语言结合后,读写数据文件和使用 RPC协议都不需要生成代码,而代码生成作为一种可选的优化只值得在静态类型语言中实现。

Avro 支持跨编程语言实现(C, C++, C#,Java, Python, Ruby, PHP),Avro 提供着与诸如 Thrift 和 Protocol Buffers 等系统相似的功能,但是在一些基础方面还是有区别的,主要是:

1、动态类型:Avro并不需要生成代码,模式和数据存放在一起,而模式使得整个数据的处理过程并不生成代码、静态数据类型等等。这方便了数据处理系统和语言的构造。
2、未标记的数据:由于读取数据的时候模式是已知的,那么需要和数据一起编码的类型信息就很少了,这样序列化的规模也就小了。
3、不需要用户指定字段号:即使模式改变,处理数据时新旧模式都是已知的,所以通过使用字段名称可以解决差异问题。

Avro 和动态语言结合后,读/写数据文件和使用 RPC 协议都不需要生成代码,而代码生成作为一种可选的优化只需要在静态类型语言中实现。

当在 RPC 中使用 Avro 时,服务器和客户端可以在握手连接时交换模式。服务器和客户端有着彼此全部的模式,因此相同命名字段、缺失字段和多余字段等信息之间通信中需要解决的一致性问题就可以容易解决。

还有,Avro 模式是用 JSON(一种轻量级的数据交换模式)定义的,这样对于已经拥有 JSON 库的语言可以容易实现。

2.Schema

Schema 通过 JSON 对象表示。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:record 类型,任意类型的一个命名字段集合,JSON对象表示。支持以下属性:

  • Records

Records使用类型名称“record”,并且支持三个必选属性。

type: 必有属性。

name: 必有属性,是一个JSON string,提供了记录的名字。

namespace,也是一个JSON

string,用来限定和修饰name属性。

doc: 可选属性,是一个JSON

string,为使用这个Schema的用户提供文档。

aliases: 可选属性,是JSON的一个string数组,为这条记录提供别名。

fields: 必选属性,是一个JSON数组,数组中列举了所有的field。每一个field都是一个JSON对象,并且具有如下属性:

 name: 必选属性,field的名字,是一个JSON string。
 doc: 可选属性,为使用此Schema的用户提供了描述此field的文档。
 type: 必选属性,定义Schema的一个JSON对象,或者            是命名一条记录定义的JSON string。
 default: 可选属性,即field的默认值,当读到缺少         这个field的实例时用到。默认值的允许的范围由这个      field的Schama的类型决定,如下表所示。其中union       fields的默认值对应于union中第一个Schema。Bytes      和fixed的field的默认值都是JSON          string,并且指向0-255的unicode都对应于无符号8位字节值0-255。

  • Enum:enum 类型,支持以下属性:

name: 必有属性,是一个JSON

string,提供了enum的名字。

namespace,也是一个JSON

string,用来限定和修饰name属性。

aliases: 可选属性,是JSON的一个string数组,为这个enum提供别名。

doc: 可选属性,是一个JSON

string,为使用这个Schema的用户提供文档。

symbols: 必有属性,是一个JSON

string数组,列举了所有的symbol,在enum中的所有symbol都必须是唯一的,不允许重复 。


  • Array:array 类型,未排序的对象集合,对象的模式必须相同。支持以下属性:

items: array中元素的Schema

  • Map:map 类型,未排序的对象键/值对。键必须是字符串,值可以是任何类型,但必须模式相同。支持以下属性: values: 用来定义map的值的Schema。Maps的key都是string。比如一个key为string,value为long的maps定义为: 引用 {"type": "map", "values": "long"}

  • Fixed:fixed 类型,一组固定数量的8位无符号字节。支持以下属性:

name: 必有属性,表示这个fixed的名称,JSON string。

namespace同上

aliases: 可选属性,同上

size: 必选属性,一个整数,志明每个值的字节数。 比如16字节的fixed可以声明为: 引用 {"type": "fixed", "size": 16, "name": "md5"}

  • Union:union 类型,模式的并集,可以用JSON数组表示,每个元素为一个模式。 每一种复杂数据类型都含有各自的一些属性,其中部分属性是必需的,部分是可选的。 Unions就像上面提到的,使用JSON的数组表示。比如 引用 ["string", "null"] 声明了一个union的Schema,其元素即可以是string,也可以是null。 Unions不能包含多个相同类型的Schema,除非是命名的record类型、命名的fixed类型和命名的enum类型。比如,如果unions中包含两个array类型,或者包含两个map类型都不允许;但是两个具有不同name的相同类型却可以。由此可见,union是通过Schema的name来区分元素Schema的,因为array和map没有name属性,当然只能存在一个array或者map。(使用name作为解析的原因是这样做会使得读写unions更加高效)。unions不能紧接着包含其他的union。

举例,一个 linked-list of 64-bit 的值:

{
  "type": "record", 
  "name": "LongList",
  "aliases": ["LinkedLongs"],                      // old name for this
  "fields" : [
    {"name": "value", "type": "long"},             // each element has a long
    {"name": "next", "type": ["null", "LongList"]} // optional next element
  ]
}

一个 enum 类型的:

{ "type": "enum",
  "name": "Suit",
  "symbols" : ["SPADES", "HEARTS", "DIAMONDS", "CLUBS"]
}

array 类型:

{"type": "array", "items": "string"}

map 类型:

{"type": "map", "values": "long"}

fixed 类型:

{"type": "fixed", "size": 16, "name": "md5"}

这里需要说明Record类型中field属性的默认值,当Record Schema实例数据中某个field属性没有提供实例数据时,则由默认值提供,具体值见下表。Union的field默认值由Union定义中的第一个Schema决定。 avro type |json type | example ---|---|-- null | null | null boolean | boolean| true int, | long | integer 1 float, |double | number 1.1 bytes |string | “\u00FF” string |string | “foo” record |object | {“a”: 1} enum |string | “FOO” array |array | [1] map |object | {“a”: 1} fixed |string | “\u00ff”

3. 序列化/反序列化

Avro 指定两种数据序列化编码方式:binary encoding 和 Json encoding。使用二进制编码会高效序列化,并且序列化后得到的结果会比较小;而 JSON 一般用于调试系统或是基于 WEB 的应用。 TODO

4. Avro Tools

为例,将 json 数据转换为 avro 数据:

将 json 数据转换为 avro 数据:
$ java -jar /usr/lib/avro/avro-tools.jar fromjson --schema-file twitter.avsc twitter.json > twitter.avro

设置压缩格式:

$ java -jar /usr/lib/avro/avro-tools.jar fromjson --codec snappy --schema-file twitter.avsc twitter.json > twitter.snappy.avro

将 avro 转换为 json:
$ java -jar /usr/lib/avro/avro-tools.jar tojson twitter.avro > twitter.json

获取 avro 文件的 schema:

$ java -jar /usr/lib/avro/avro-tools.jar getschema twitter.avro > twitter.avsc

将 Avro 数据编译为 Java:

$ java -jar /usr/lib/avro/avro-tools.jar compile schema twitter.avsc java .

参考文献

https://unmi.cc/avro-tools-jq-view-apache-avro-file/#more-8102

https://www.cnblogs.com/fillPv/p/5009737.html

https://blog.csdn.net/strongyoung88/article/details/54293263

https://blog.csdn.net/bingduanlbd/article/details/52006520

https://blog.csdn.net/bingduanlbd/article/details/52006520

http://fangjian0423.github.io/2016/02/21/avro-intro/

猜你喜欢

转载自my.oschina.net/112612/blog/1805384