我对Avro进行了调查
我做了一些关于Apache Avro的调查。由于有很多地方我不太理解,所以如果有任何指正或评论,请务必留言。
1. 概括
Avro是一种用于系统间数据交换的格式,具有模式定义和二进制编码的特点。当JSON中的类型不明确且基于字符串的效率低下且令人困惑时,可使用Avro。类似的格式还有Protocol Buffers和Message Pack等。
主要用于文件格式、为RPC定义的协议和Kafka等消息格式。以下不会涉及RPC,因为对此不甚了解。
在日本语中,Apache Avro与Protocol Buffers的资料总结了Avro的概述以及与Protocol Buffers之间的差异,十分易于理解。
关于C、C++、C#、Java、PHP、Python和Ruby,官方都有相应的库可用,但是根据语言的不同,对于(特别是新功能方面的)支持程度似乎略有差异。我认为Go语言主要使用linkedin/goavro。以下说明是以Java为基础的。
2. 主要功能
2.1 数据模式定义
在avsc文件中定义模式。提供了以下数据类型,可以组合来定义字段。尽管稍旧,但参考Oracle NoSQL数据库起步指南的第7章Avro模式的日文文档。
Logical Type是一种派生类型,它以Primitive Type作为物理形式进行序列化。
除了可以使用JSON格式来描述模式之外,还可以通过IDL来创建模式。使用IDL可以使用import等功能。
2.1.1 示例模式的例子
从http://avro.apache.org/docs/current/spec.html获取
{"namespace": "example.avro",
"type": "record",
"name": "User",
"fields": [
{"name": "name", "type": "string"},
{"name": "favorite_number", "type": ["int", "null"]},
{"name": "favorite_color", "type": ["string", "null"]}
]
2.1.2 以 IDL 进行模式定义的示例
从AvroHubTool根据Avro IDL合成Avro schema。
(Note: The provided link appears to be written in Japanese, not Chinese.)
@namespace("avro.examples.baseball")
protocol Baseball {
import schema "name.avsc";
import schema "coache.avsc";
import schema "position.avsc";
import schema "player.avsc";
record Team {
Player player;
Coache coache;
}
}
2.1.3 数据结构演进
在Avro中,有互換性的規則,可以在更改模式時保持互換性。但是,公式規範很難理解,所以了解viniciusccarvalho/schema-evolution-samples的解釋和示例,以及Confluent Platform各個組件的特點更容易理解。
为了保持前向兼容性,在向模式中添加列时需要指定默认值。
2.2 数据格式
Avro提供了三种数据格式,可以根据用途进行选择。由于读写数据需要模式,因此需要考虑头部开销和模式管理来进行决策。
Object Container Files(OCF)的格式可以进行deflate/snappy压缩。此外,它还被BigQuery、RedShift、Spark等支持。您还可以加载Amazon EMR的Avro格式数据到Amazon Redshift进行引用。
为了消息传输目的,由于对象容器文件(Object Container Files)格式的开销较大,所以提供了轻量级的单一对象编码(Single-Object Encoding)作为替代。不过,也可以自行在其中嵌入模式的版本等来解决这个问题。
作为解决动态模式的机制之一,Confluent Schema Registry是一个相对复杂的选择。还可以参考Confluent Platform的各个组件的特点。
2.3 用于序列化的主要类
基本上,可以使用DatumWriter的任何子类以及Encoder或FileWriter进行序列化。序列化的示例请参考Getting Started (Java)。在反序列化中,使用相应的Reader/Decoder。
这个章节是《Oracle NoSQL Database入门指南》的第8章,虽然略微陈旧,但有关Avro绑定的日语文档可在这里找到。
在Python或Ruby中,不支持或者说不需要生成类,只需要相应的GenericDatumWriter。可以参考Python的入门指南或者Ruby中的Avro文档。
考虑到模式演化,在使用SpecificDatumWriter时,我有点困惑如何对自动生成的类进行版本管理。
附录
commercehub-oss/gradle-avro-plugin Gradleのplugin
[AVRO-1891] JavaでLogical Typeを含むUnionができないというバグ。Nullを許可する場合にはunionを使うので、現状ではLogical TypeでNullを許可することができない。1.8.3で対応予定。
GADGT: The futue of gogen-avro
How to encode/decode Kafka messages using Avro binary encoder? – Stack Overflow