从大型 ByteArrayOutputSteam 了解 Avro 反序列化
Posted
技术标签:
【中文标题】从大型 ByteArrayOutputSteam 了解 Avro 反序列化【英文标题】:Understanding Avro Deserialization from a Large ByteArrayOutputSteam 【发布时间】:2013-02-25 08:09:47 【问题描述】:我的印象是ByteArrayOutputStream
的内存效率不高,因为它的所有内容都存储在内存中。
同样,在大型流上调用 toByteArray
似乎“扩展性很差”。
那么,为什么在 Tom White 的书 Hadoop: the Definitive Guide 中的示例中同时使用它们:
ByteArrayOutputStream out = new ByteArrayOutputStream;
Decoder decoder = DecoderFactory().defaultFactory().createBinaryDecoder(out.toByteArray(), null);
“大数据”不是 Avro 的标准吗?我错过了什么?
编辑 1:我正在尝试做的事情 - 假设我正在通过 websocket 流式传输 avros。如果我想反序列化多个记录,而不仅仅是放在它自己的ByteArrayOutoputStream
中的记录,该示例会是什么样子?
有没有更好的方法来为BinaryDecoder
提供一个字节[]?或者也许是不同类型的流?或者我应该为每个流发送 1 条记录,而不是加载具有多条记录的流?
【问题讨论】:
如果您具体说明您打算使用 Avro 做什么,您的问题会更容易回答。 长话短说,我正在扩展 Salat-Avro 以支持将 Scala 案例类序列化到 Avro 数据文件或从 Avro 数据文件序列化。我正在尝试实现数据文件和内存序列化方法之间的一致性。对于大型数据文件,我可以有效地反序列化 avros,因为 DataFileReader 是记录上的 iterator 并且不会将评估保存在内存中。与数据文件相比,内存中的反序列化不是通过迭代器在 Steam 上完成的,而是通过在其数据源上重复调用函数的求值来完成的。 更长的故事是“重复调用一个函数”对于少量记录是没有问题的,因为我可以通过cons
ing函数的结果生成一个Stream
。但是随着记录数量的增加,Stream
由于内存使用而变得不切实际。可悲的是,Iterator
与 cons
没有类比,当我注意到问题中的规范示例可能不支持大量记录时,我正想知道该怎么做。
【参考方案1】:
ByteArrayOutputStream 在处理小型对象(如中小型图像)或固定大小的请求/响应时很有意义。它在内存中并且不接触磁盘,因此这对性能非常有用。将它用于 1 TerraByte 的数据没有任何意义。可能这是一个试图在书中保持一个例子小而独立的例子,以免偏离重点。
编辑:现在我知道你要去哪里了,我想建立一个管道。从流中拉出一条消息(所以我假设您可以从 HTTP 对象中获取 InputStream)并使用无内存方法处理它或将其扔到队列中并让线程池处理具有内存的队列-less 方法。因此,对此的要求是 1) 能够在将 Avro 消息从流中拉出时检测它们之间的边界并具有解码方法。
解码的方法似乎是将每条消息的字节读取到一个字节数组中,然后将其交给您的 BinaryDecoder(在找到消息边界之后)。
【讨论】:
感谢您的帮助。以上是关于从大型 ByteArrayOutputSteam 了解 Avro 反序列化的主要内容,如果未能解决你的问题,请参考以下文章