参考自http://avro.apache.org/docs/current/spec.html
Avro 1.4.1规范定义了Avro序列化系统,它即将成为官方规范,Avro的各种实现方式必须遵循该规范。
Schema定义
AVRO的Schema是用JSON的格式表示的,Schema可以用
- JSON String 来命名一个定义的类型
- JSON 对象,形式如:
-
引用{“type”: “typeName” …attributes…}
typeName可以是一个原生类型或者下面将要定义的衍生类型。这篇文档没有定义JSON对象中的属性,这些属性可以成为meta data,但是不能影响序列化数据的格式。
- JSON 数组,代表内嵌类型的并集(union)。
原生类型
原生类型如下所示:
- null: 表示没有值
- boolean: 表示一个二进制布尔值
- int: 表示32位有符号整数
- long: 表示64位有符号整数
- float: 表示32位的单精度浮点数(IEEE 754)
- double: 表示64位双精度浮点数(IEEE 754)
- bytes: 表示8位的无符号字节序列
- string: Unicode 编码的字符序列
- 总共就这8种原生数据类型,这些原生数据类型均没有明确的属性。
原生数据类型也可以使用JSON定义类型名称,比如schema “string”和{“type”: “string”}是同义且相等的。
复杂类型
AVRO支持6种类型的复杂类型,分别是:records, enums, arrays, maps, unions and fixed.
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。
field default valuesavro 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” order: 可选属性,指定这个field如何影响record的排序。有效的可选值为“ascending”(默认),”descending”和”ignore”
alias: JSON的string数组,为这个field提供别名。比如,一个64位值的链表定义为
引用{
“type”: “record”,
“name”: “LongList”,
“aliases”: [“LinkedLongs”], // old name for this
“fields” : [
{“name”: “value”, “type”: “long”}, // each element has a long
{“name”: “next”, “type”: [“LongList”, “null”]} // optional next element
]
}
Enums
Enums使用的名为“enum”的type并且支持如下的属性:
- name: 必有属性,是一个JSON string,提供了enum的名字。
- namespace,也是一个JSON string,用来限定和修饰name属性。
- aliases: 可选属性,是JSON的一个string数组,为这个enum提供别名。
- doc: 可选属性,是一个JSON string,为使用这个Schema的用户提供文档。
- symbols: 必有属性,是一个JSON string数组,列举了所有的symbol,在enum中的所有symbol都必须是唯一的,不允许重复。比如下面的例子:
-
引用{ “type”: “enum”,
“name”: “Suit”,
“symbols” : [“SPADES”, “HEARTS”, “DIAMONDS”, “CLUBS”]
}
Arrays
Array使用名为”array”的type,并且支持一个属性
- items: array中元素的Schema
- 比如一个string的数组声明为:
引用{“type”: “array”, “items”: “string”}
Maps
Map使用名为”map”的type,并且支持一个属性
- values: 用来定义map的值的Schema。Maps的key都是string。比如一个key为string,value为long的maps定义为:
-
引用{“type”: “map”, “values”: “long”}
Unions
Unions就像上面提到的,使用JSON的数组表示。比如
声明了一个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。
Fixed
Fixed类型使用”fixed”的type name,并且支持三个属性:
- name: 必有属性,表示这个fixed的名称,JSON string。
- namespace同上
- aliases: 可选属性,同上
- size: 必选属性,一个整数,志明每个值的字节数。
- 比如16字节的fixed可以声明为:
引用{“type”: “fixed”, “size”: 16, “name”: “md5”}
Names
Record, enums 和 fixed都是命名的类型,这三种类型都各有一个全名,全名有两部分组成:名称和命名空间。名称的相等是定义在全名基础上的。
全名的名字部分和record的field名字必须:
- 以[A-Za-z_]开头
- 接下来的名字中只能包含[A-Za-z0-9_]
- namespace是以点分隔的一系列名字。
In record, enum and fixed definitions, the fullname is determined in one of the following ways:
在record、enum和fixed的定义中,全名由以下的任意一条决定: - 同时指定name和namespace,比如使用 “name”: “X”, “namespace”: “org.foo”来表示全名org.foo.X。
- 指定全名。如果name中包含点号,则认为是全名。比如用 “name”: “org.foo.X” 表示全名org.foo.X。
- 仅仅指定name,name中没有点号。在这种情况下命名空间取自距离最近的父亲的Schema或者protocol。比如声明了”name”: “X”, 这段声明在一条记录“org.foo.Y”的field中,那么X的全名就是org.foo.X。
- 原生类型没有命名空间,并且在不可以在命名空间中定义原生类型。如果多个全名定义相等的话,一个Schema可以包含多个全名定义。
研究了AVRO的规范,比较形象的图形表达了文件中内容布局,仅做参考。详细说明在图形下方。
使用AVRO标准系列化生成二进制的文件,该文件总体上由文件头(Header)和数据块(Data Block)及同步标识(Synchronization marker)三部分组成。
- 文件头为标识为Header的青色大框部分。
- 数据块为文件头下方紧邻的灰色的Data Block部分。
- 同步标识为数据块下方紧接着的橘色的Synchronization marker部分。
AVRO通过使用同步标识,将大块数据分割成小块,连续存储在同一个文件中,便于并发处理,即不同线程可以相互无影响的同时操作不同的数据块。因此,在上图最下方的数据块之后,根据情况,会有更多的同步标识和数据块。
AVRO的文件头由三部分组成,如上图所示。
- 文件头由四个字节’O’, ‘b’, ‘j’开始,后面紧接着1,一般称这四个字节为魔术字符(magic)
- 紧接着文件头的是AVRO的Meta Data
- 文件头的最后由同步标识结尾
It’s in fact very complex in this active life to listen news on TV,
so I only use the web for that purpose, and get the hottest
information.
Howdy! This article couldn’t be written any better! Going through this post reminds me of my previous roommate!
He constantly kept talking about this. I will forward this post to him.
Pretty sure he will have a very good read. Thanks for sharing!
I always spent my half an hour to read this weblog’s posts
daily along with a cup of coffee.
You have noted very interesting points! ps decent website.