我们正在评估用于存储的 avro v/s thrift。在这一点上,Avro 似乎是我们的选择,但是文档指出模式在序列化时与数据一起存储,有没有办法避免这种情况,因为我们负责生产和消费数据,我们想看看是否我们可以避免序列化模式,而且序列化数据与模式的大小差异是否比没有模式的数据大得多?
3 回答
聚会有点晚了,但您实际上并不需要将实际模式与每条记录一起存储。但是,您确实需要一种从每条记录的序列化格式返回到原始模式的方法。
因此,您可以使用写入 avro 记录内容和模式 ID 的模式存储 + 自定义序列化程序。在读取时,您可以读回该架构 ID,从架构存储中检索它,然后使用该架构来补充记录内容。如果您的模式存储是远程的,则使用本地缓存的奖励积分。
这正是Oracle 的 NoSQL DB采用存储高效方式管理模式的方法(它也可以在 AGPL 许可下使用)。
全面披露:目前且从未受雇于 Oracle 或 Sun,或曾在上述商店工作。最近才发现:)
我很确定您将始终需要将架构与数据一起存储。这是因为 Avro 在读取和写入 .avro 文件时会使用它。
根据http://docs.oracle.com/cd/NOSQL/html/GettingStartedGuide/avroschemas.html:
您使用 Avro 绑定将模式应用于 Oracle NoSQL 数据库记录的值部分。这些绑定用于在写入值之前对其进行序列化,并在读取值之后对其进行反序列化。这些绑定的使用要求您的应用程序使用 Avro 数据格式,这意味着每个存储的值都与一个模式相关联。
就大小差异而言,您只需存储一次模式,因此在大方案中,它并没有太大的区别。我的架构占用 105.5KB(这是一个非常大的架构,你的架构不应该那么大),每个序列化值占用 3.3KB。我不确定数据的原始 json 会有什么区别,但根据我发布的链接:
每个值的存储都没有任何元数据,除了一个小的内部模式标识符,大小在 1 到 4 个字节之间。
但我相信这可能只是针对单一、简单的价值观。
顺便说一句,这对我来说是在 HDFS 上。
感谢 JGibel,我们的数据最终最终会出现在 HDFS 中,并且对象容器文件格式确实确保架构仅作为文件头写入。
对于 HDFS 以外的用途,我错误地假设架构将附加到每个编码数据,但事实并非如此,这意味着您需要架构来反序列化它,但序列化的数据不必具有架构字符串附在它上面。
例如
DatumWriter<TransactionInfo> eventDatumWriter = new SpecificDatumWriter<TransactionInfo>(TransactionInfo.class);
TransactionInfo t1 = getTransaction();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BinaryEncoder becoder = EncoderFactory.get().binaryEncoder(baos, null);
eventDatumWriter.setSchema(t1.getSchema());
eventDatumWriter.write(t1, becoder);
becoder.flush();