Avro 模式演变在反序列化时抛出 EOFException

gnu*_*ger 6 java scala sbt avro

我有一个 no-sql 数据库,在其中存储序列化的 avro 对象。我使用sbt-avro插件专门生成 java 类addSbtPlugin("com.cavorite" % "sbt-avro-1-8" % "1.1.5")。现在我想向架构添加新字段,并且还希望与现有数据向后兼容。但是使用新模式对旧数据进行反序列化会引发问题java.io.EOFException

旧架构:

{
  "name": "DNode",
  "namespace": "my.model",
  "type": "record",
  "fields": [
    {"name": "prev", "type": ["null", "string"]},
    {"name": "next", "type": ["null", "string"]}
  ]
}
Run Code Online (Sandbox Code Playgroud)

新架构:

{
  "name": "DNode",
  "namespace": "my.model",
  "type": "record",
  "fields": [
    {"name": "prev", "type": ["null", "string"]},
    {"name": "next", "type": ["null", "string"]},
    {"name": "size", "type": ["null", "long"], "default": null}
  ]
}
Run Code Online (Sandbox Code Playgroud)

反序列化代码

  def deserialize(bytes: Array[Byte]) = {
    val reader = new SpecificDatumReader[DNode](classOf[DNode])
    val decoder = DecoderFactory.get().binaryDecoder(bytes, null)
    reader.read(null, decoder)
  }
Run Code Online (Sandbox Code Playgroud)

投掷

java.io.EOFException
    at org.apache.avro.io.BinaryDecoder.ensureBounds(BinaryDecoder.java:473)
    at org.apache.avro.io.BinaryDecoder.readInt(BinaryDecoder.java:128)
    at org.apache.avro.io.BinaryDecoder.readIndex(BinaryDecoder.java:423)
    at org.apache.avro.io.ResolvingDecoder.doAction(ResolvingDecoder.java:290)
    at org.apache.avro.io.parsing.Parser.advance(Parser.java:88)
    at org.apache.avro.io.ResolvingDecoder.readIndex(ResolvingDecoder.java:267)
    at org.apache.avro.generic.GenericDatumReader.readWithoutConversion(GenericDatumReader.java:179)
    at org.apache.avro.specific.SpecificDatumReader.readField(SpecificDatumReader.java:116)
    at org.apache.avro.generic.GenericDatumReader.readRecord(GenericDatumReader.java:222)
    at org.apache.avro.generic.GenericDatumReader.readWithoutConversion(GenericDatumReader.java:175)
    at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:153)
    at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:145)
...
Run Code Online (Sandbox Code Playgroud)