提问者:小点点

在avro中存储模式的优势是什么?


我们需要序列化一些数据以放入solr和hadoop。

我正在评估相同的序列化工具。

我名单上的前两个是Gson和Avro。

据我所知,Avro=GsonJSON

如果这是正确的,我不明白为什么Avro在Solr/Hadoop中如此受欢迎?

我在网上搜索了很多,但找不到一个正确的答案。

到处都说Avro很好,因为它存储了模式。我的问题是如何处理该模式?

对于Hadoop中非常大的对象来说,这可能很好,在Hadoop中,单个对象存储在多个文件块中,这样将模式与每个部分一起存储有助于更好地分析它。但即使在这种情况下,模式也可以单独存储,仅仅引用它就足以描述模式。我看不出为什么模式应该是每个部分的一部分。

如果有人能给我一些好的用例,Avro是如何帮助他们的,而Gson/Jackson不足以达到这个目的,那将是非常有帮助的。

此外,Avro网站的官方留档说我们需要给Avro一个模式来帮助它生成模式数据。我的问题是,如果模式是输入的,并且随着数据的JSON表示一起发送到输出,那么Avro实现了什么额外的功能?我可以通过使用JSON序列化对象,添加我的输入模式并将其命名为Avro而不自己做到这一点吗?

我真的很困惑!


共3个答案

匿名用户

  1. 不断演变的模式

假设您最初为员工类设计了一个这样的模式

{
{"name": "emp_name", "type":"string"},
{"name":"dob", "type":"string"},
{"name":"age", "type":"int"}
}

后来你意识到年龄是多余的,并将其从模式中删除。

{
{"name": "emp_name", "type":"string"},
{"name":"dob", "type":"string"}
}

在此模式更改之前序列化和存储的记录呢?您将如何读回这些记录?

这就是为什么avro读取器/反序列化器要求读取器和写入器模式。它在内部进行模式解析,即。它试图使旧模式适应新模式。

转到此链接-http://avro.apache.org/docs/1.7.2/api/java/org/apache/avro/io/parsing/doc-files/parsing.html-部分“使用动作符号的分辨率”

在这种情况下,它确实跳过了动作,即它忽略了读取“age”。它还可以处理字段从int更改为long等情况。

这是一篇解释模式演变的非常好的文章-http://martin.kleppmann.com/2012/12/05/schema-evolution-in-avro-protocol-buffers-thrift.html

对于单个文件中的多条记录,Schema仅存储一次。

大小,以很少的字节编码。

匿名用户

我认为模式进化解决的关键问题之一没有被明确提及,这就是为什么它会给新来者带来如此多的困惑。

一个例子将澄清这一点:

假设一家银行存储其所有交易的审计日志。这些日志具有特定的格式,需要存储至少10年。保存这些日志的系统应该适应这10年中不断发展的格式,这也是非常可取的。

此类条目的模式不会经常更改,假设平均每年两次,但每个模式都会有大量条目。如果我们不跟踪模式,那么一段时间后,我们将需要查阅非常旧的代码来找出当时存在的字段,并继续添加if-else语句来处理不同的格式。通过所有这些格式的模式存储,我们可以使用模式演变功能自动将一种格式转换为另一种格式(如果您为Avro提供较旧和较新的模式,Avro会自动执行此操作)。这节省了应用程序在其代码中添加大量if-else语句,也使其更易于管理,因为我们通过查看存储的模式集很容易知道我们拥有的所有格式(模式通常存储在单独的存储中,数据只有一个指向其模式的ID)。

模式演进的另一个优点是,新格式的生产者可以安全地生产具有新模式的对象,而无需等待下游消费者首先更改。下游消费者可以内置逻辑来简单地暂停处理,除非他们对与新格式关联的新模式具有可见性。这种自动暂停非常有助于保持系统在线并适应新模式的处理逻辑。

总之,模式演进通过使用自动格式转换帮助新客户端读取旧格式,也帮助旧客户端以优雅的方式暂停处理,直到它们能够理解新格式。

匿名用户

从模式进化的角度来看,拥有模式是好的,但不是JSON做不到的事情。JSON和Avro完全一样。

Avro的主要特点是它是二进制的。所以让我们说,你的记录是:

{
  {"name": "emp_name", "type":"string"},
  {"name":"dob", "type":"string"},
  {"name":"age", "type":"int"}
}

Avro将上述数据部分存储为:“John”

在这里

所以没有模式,上面的数据是无用的!没有模式,你不知道这些值意味着什么。

这就是二进制和非二进制格式的区别。二进制格式只有值,这使得它们非常紧凑。像JSON和XML这样的文本格式有一遍又一遍重复的模式,因此它们比二进制文件大2倍以上。

另一个比较:二进制的整数只需要32位,但JSON形式的整数是以文本格式存储的数字。

{"some_number": 43847384}

上面JSON中的数字存储不像JSON中的32位整数,它都是文本,占用8个字符*8位=64位,甚至更多,具体取决于数字的长度。

所以JSON中的模式不是可选的。如果你必须使用二进制格式,这是必须的。