Avro
Apache Avro
Avro 是 Hadoop 中的一个子项目,也是 Apache 中一个独立的项目,Avro 是一个基于二进制数据传输高性能的中间件。在 Hadoop 的其他项目中例如 HBase(Ref)和 Hive(Ref)的 Client 端与服务端的数据传输也采用了这个工具。Avro 是一个数据序列化的系统。Avro 可以将数据结构或对象转化成便于存储或传输的格式。Avro 设计之初就用来支持数据密集型应用,适合于远程或本地大规模数据的存储和交换。
特性
Avro 支持跨编程语言实现(C, C++, C#,Java, Python, Ruby, PHP),类似于 Thrift,但是 Avro 的显著特征是:Avro 依赖于模式,动态加载相关数据的模式,Avro 数据的读写操作很频繁,而这些操作使用的都是模式,这样就减少写入每个数据文件的开销,使得序列化快速而又轻巧。这种数据及其模式的自我描述方便了动态脚本语言的使用。当 Avro 数据存储到文件中时,它的模式也随之存储,这样任何程序都可以对文件进行处理。如果读取数据时使用的模式与写入数据时使用的模式不同,也很容易解决,因为读取和写入的模式都是已知的。
Avro 提供:
- 丰富的数据结构。
- 一个紧凑的,快速的,二进制的数据格式。
- 一个容器文件,来存储持久化数据。
- 远程过程调用(RPC)。
- 简单的动态语言集成。
- 代码生成不需要读写数据文件,也不要使用或实现 RPC 协议。代码生成是作为一个可选的优化,只对静态类型的语言值得实现。
JSON 是一种轻量级的数据传输格式,对于大数据集,JSON 数据会显示力不从心,因为 JSON 的格式是 key:value 型,每条记录都要附上 key 的名字,有的时候,光 key 消耗的空间甚至会超过 value 所占空间,这对空间的浪费十分严重,尤其是对大型数据集来说,因为它不仅不够紧凑,还要重复地加上 key 信息,不仅会造成存储空间上的浪费,更会增加了数据传输的压力,从而给集群增加负担,进而影响整个集群的吞吐量。而采用 Avro 数据序列化系统可以比较好的解决此问题,因为用 Avro 序列化后的文件由 schema 和真实内容组成,schema 只是数据的元数据,相当于 JSON 数据的 key 信息,schema 单独存放在一个 JSON 文件中,这样一来,数据的元数据只存了一次,相比 JSON 数据格式的文件,大大缩小了存储容量。从而使得 Avro 文件可以更加紧凑地组织数据。
序列化
Apache Avro 是一个数据序列化系统。序列化就是将对象转换成二进制流,相应的反序列化就是将二进制流再转换成对应的对象。因此,Avro 就是用来在传输数据之前,将对象转换成二进制流,然后此二进制流达到目标地址后,Avro 再将二进制流转换成对象。
我们用 Avro IDL 编写的示例模式可能如下所示:
record Person {
string userName;
union { null, long } favoriteNumber = null;
array<string> interests;
}
等价的 JSON 表示:
{
"type": "record",
"name": "Person",
"fields": [
{"name": "userName", "type": "string"},
{"name": "favoriteNumber", "type": ["null", "long"], "default": null},
{"name": "interests", "type": {"type": "array", "items": "string"}
]
}
首先,请注意架构中没有标签号码,Avro 二进制编码只有 32 个字节长,这是我们所见过的所有编码中最紧凑的编码字节序列的分解如下图所示。
如果您检查字节序列,您可以看到没有什么可以识别字段或其数据类型编码只是由连在一起的值组成一个字符串只是一个长度前缀,后跟 UTF-8 字节,但是在被包含的数据中没有任何内容告诉你它是一个字符串它可以是一个整数,也可以是其他的整数整数使用可变长度编码(与 Thrift 的 CompactProtocol 相同)进行编码。
为了解析二进制数据,您按照它们出现在架构中的顺序遍历这些字段,并使用架构来告诉您每个字段的数据类型。这意味着如果读取数据的代码使用与写入数据的代码完全相同的模式,则只能正确解码二进制数据。阅读器和作者之间的模式不匹配意味着错误地解码数据。