1 个不稳定版本
0.7.0 | 2022 年 8 月 12 日 |
---|---|
0.6.5 |
|
#862 in 编码
305KB
6.5K SLoC
mz-avro
在 Rust 中操作 Apache Avro 的库。
此文档正在建设中。
许可证
本项目采用 Apache 许可证,版本 2.0。请注意,这不是由 Apache Avro 维护的官方项目。
贡献
鼓励每个人做出贡献!您可以通过在 GitHub 仓库上分叉并提交拉取请求或打开问题来做出贡献。所有贡献都将采用 Apache 许可证,版本 2.0 进行许可。
lib.rs
:
avro
Apache Avro 是一种数据序列化系统,它提供了丰富的数据结构和紧凑、快速的二进制数据格式。
Avro 中的所有数据都是模式化的,如下例所示
{
"type": "record",
"name": "test",
"fields": [
{"name": "a", "type": "long", "default": 42},
{"name": "b", "type": "string"}
]
}
在 Rust 中处理 Avro 数据的基本有两种方式
- 基于 Avro 模式作为 Avro 特化的数据类型;
- 作为通用的 Rust 类型,具有自定义序列化逻辑实现
AvroDecode
(目前仅支持反序列化,不支持序列化)。
avro 提供了一种轻松有效地读取和写入这两种数据表示的方法。
安装库
添加到您的 Cargo.toml
[dependencies]
avro = "x.y"
或者如果您想利用 Snappy 编码器
[dependencies.avro]
version = "x.y"
features = ["snappy"]
定义一个模式
Avro 数据不能没有 Avro 模式。模式在写入和读取时都 必须 使用,并且它们携带有关我们处理的数据类型的有关信息。Avro 模式用于模式验证和解析 Avro 数据。
Avro 模式以 JSON 格式定义,并可以从原始字符串中解析出来
use mz_avro::Schema;
let raw_schema = r#"
{
"type": "record",
"name": "test",
"fields": [
{"name": "a", "type": "long", "default": 42},
{"name": "b", "type": "string"}
]
}
"#;
// if the schema is not valid, this function will return an error
let schema: Schema = raw_schema.parse().unwrap();
// schemas can be printed for debugging
println!("{:?}", schema);
有关模式和您可以在其中封装的信息的更多信息,请参阅Avro 规范的相关部分。
写入数据
一旦我们定义了模式,我们就可以将数据序列化为 Avro,并在过程中对其进行验证。
注意: 该库还提供了一个低级接口,用于在不生成标记和头信息的情况下对单个数据进行Avro字节码编码(适用于高级用途),但我们强烈建议使用Writer
接口以实现完全的Avro兼容性。如果您感兴趣,请阅读API参考。
鉴于我们上面定义的模式是一个Avro 记录,我们将使用库提供的关联类型来指定要序列化的数据。
use mz_avro::types::Record;
use mz_avro::Writer;
#
// a writer needs a schema and something to write to
let mut writer = Writer::new(schema.clone(), Vec::new());
// the Record type models our Record schema
let mut record = Record::new(schema.top_node()).unwrap();
record.put("a", 27i64);
record.put("b", "foo");
// schema validation happens here
writer.append(record).unwrap();
// flushing makes sure that all data gets encoded
writer.flush().unwrap();
// this is how to get back the resulting avro bytecode
let encoded = writer.into_inner();
大多数情况下,模式倾向于将记录定义为一个顶层容器,封装所有要转换的字段并为其提供文档,但如果我们要直接定义一个Avro值,库通过Value
接口提供了这种能力。
use mz_avro::types::Value;
let mut value = Value::String("foo".to_string());
使用编解码器压缩数据
Avro在编码数据时支持三种不同的压缩编解码器
- Null:不压缩数据;
- Deflate:使用RFC 1951中指定的deflate算法写入数据块,通常使用zlib库实现。注意,此格式(与RFC 1950中的“zlib格式”不同)没有校验和。
- Snappy:使用Google的Snappy压缩库。每个压缩块后面跟随块中未压缩数据的4字节大端CRC32校验和。您必须启用
snappy
功能才能使用此编解码器。
要指定用于压缩数据的编解码器,只需在创建Writer
时指定即可。
use mz_avro::Writer;
use mz_avro::Codec;
#
let mut writer = Writer::with_codec(schema, Vec::new(), Codec::Deflate);
读取数据
就读取Avro编码数据而言,我们可以直接使用与数据一起编码的模式来读取它们。库将自动为我们完成,就像它已经为我们完成了压缩编解码器一样。
use mz_avro::Reader;
#
// reader creation can fail in case the input to read from is not Avro-compatible or malformed
let reader = Reader::new(&input[..]).unwrap();
如果,相反,我们想指定一个与数据写入时使用的模式不同(但兼容)的读取器模式,我们可以按以下方式操作。
use mz_avro::Schema;
use mz_avro::Reader;
#
let reader_raw_schema = r#"
{
"type": "record",
"name": "test",
"fields": [
{"name": "a", "type": "long", "default": 42},
{"name": "b", "type": "string"},
{"name": "c", "type": "long", "default": 43}
]
}
"#;
let reader_schema: Schema = reader_raw_schema.parse().unwrap();
// reader creation can fail in case the input to read from is not Avro-compatible or malformed
let reader = Reader::with_schema(&reader_schema, &input[..]).unwrap();
在读取数据时,库还将自动执行模式解析。
有关模式兼容性和解析的更多信息,请参阅Avro规范。
处理Rust中的Avro数据反序列化有两种方法,如下所示。
注意: 该库还提供了一个低级接口,用于在不生成标记和头信息的情况下对单个数据进行Avro字节码解码(适用于高级用途),但我们强烈建议使用Reader
接口以利用所有Avro功能。如果您感兴趣,请阅读API参考。
Avro的方式
我们可以直接从Reader
迭代器中读取Value
实例。
use mz_avro::Reader;
#
let mut reader = Reader::new(&input[..]).unwrap();
// value is a Result of an Avro Value in case the read operation fails
for value in reader {
println!("{:?}", value.unwrap());
}
自定义反序列化(高级)
通过为将决定如何解码各种模式片段的一个或多个结构体实现AvroDecode
,可以避免解码到Value
的中间阶段。
此API正在变动,更完整的文档即将推出。目前,Materialize提供了一个最完整的示例。
依赖项
~5.5–8MB
~145K SLoC