2013-03-11 3 views
11

Ich habe zwei Fragen:Avro Schemaevolution

  1. Ist es möglich, den gleichen Leser zu verwenden und Aufzeichnungen analysieren, die mit zwei Schemas geschrieben wurden, die kompatibel sind, z.B. Schema V2 hat nur ein zusätzliches optionales Feld im Vergleich zu Schema V1 und ich möchte, dass der Leser beides versteht? Ich denke, die Antwort hier ist nein, aber wenn ja, wie mache ich das?

  2. habe ich versucht, einen Datensatz mit Schema V1 zu schreiben und es mit Schema V2 zu lesen, aber ich bekomme die folgende Fehlermeldung:

    org.apache.avro.AvroTypeException: Gefunden foo, erwartet foo

ich benutzte Avro-1.7.3 und:

writer = new GenericDatumWriter<GenericData.Record>(SchemaV1); 
    reader = new GenericDatumReader<GenericData.Record>(SchemaV2, SchemaV1); 

Hier sind einige Beispiele der beiden Schemata (ich versucht habe auch einen Namespace hinzufügen, aber kein Glück).

Schema V1:

{ 
"name": "foo", 
"type": "record", 
"fields": [{ 
    "name": "products", 
    "type": { 
     "type": "array", 
     "items": { 
      "name": "product", 
      "type": "record", 
      "fields": [{ 
       "name": "a1", 
       "type": "string" 
      }, { 
       "name": "a2", 
       "type": {"type": "fixed", "name": "a3", "size": 1} 
      }, { 
       "name": "a4", 
       "type": "int" 
      }, { 
       "name": "a5", 
       "type": "int" 
      }] 
     } 
    } 
}] 
} 

Schema V2:

{ 
"name": "foo", 
"type": "record", 
"fields": [{ 
    "name": "products", 
    "type": { 
     "type": "array", 
     "items": { 
      "name": "product", 
      "type": "record", 
      "fields": [{ 
       "name": "a1", 
       "type": "string" 
      }, { 
       "name": "a2", 
       "type": {"type": "fixed", "name": "a3", "size": 1} 
      }, { 
       "name": "a4", 
       "type": "int" 
      }, { 
       "name": "a5", 
       "type": "int" 
      }] 
     } 
    } 
}, 
{ 
      "name": "purchases", 
      "type": ["null",{ 
        "type": "array", 
        "items": { 
          "name": "purchase", 
          "type": "record", 
          "fields": [{ 
            "name": "a1", 
            "type": "int" 
          }, { 
            "name": "a2", 
            "type": "int" 
          }] 
        } 
      }] 
}] 
} 

Vielen Dank im Voraus.

Antwort

9

Ich stieß auf das gleiche Problem. Das könnte ein Fehler von avro sein, aber Sie können wahrscheinlich umgehen, indem Sie "default": null zum Feld "purchase" hinzufügen.

mein Blog für weitere Details prüfen: http://ben-tech.blogspot.com/2013/05/avro-schema-evolution.html

+5

Standardwerte sind ein Muss, wenn Schemaevolution verwenden. Wenn Sie keinen Standardwert für ein Feld angeben, das im Leserschema, aber nicht im Writer-Schema vorhanden ist, kann Avro nicht herausfinden, wie dieses neue Feld in der analysierten Struktur erstellt wird. – LiMuBei

0

Sie können Gegenteil davon tun. Sie können Datenschem 1 analysieren und Daten aus Schema 2 schreiben. Beacause zum Schreibzeitpunkt schreibt es Daten in Datei und wenn wir kein Feld zur Lesezeit zur Verfügung stellen, wird es in Ordnung sein. Aber wenn wir weniger Feld schreiben als lesen, wird es das zusätzliche Feld zur Lesezeit nicht erkennen, so wird es einen Fehler geben.

0

Der beste Weg besteht darin, eine Schemazuordnung zu haben, um das Schema wie die Confluent Avro Schema-Registrierung zu verwalten.

Key Imbissbuden:

1. Unlike Thrift, avro serialized objects do not hold any schema. 
2. As there is no schema stored in the serialized byte array, one has to provide the schema with which it was written. 
3. Confluent Schema Registry provides a service to maintain schema versions. 
4. Confluent provides Cached Schema Client, which checks in cache first before sending the request over the network. 
5. Json Schema present in “avsc” file is different from the schema present in Avro Object. 
6. All Avro objects extends from Generic Record 
7. During Serialization : based on schema of the Avro Object a schema Id is requested from the Confluent Schema Registry. 
8. The schemaId which is a INTEGER is converted to Bytes and prepend to serialized AvroObject. 
9. During Deserialization : First 4 bytes are removed from the ByteArray. 4 bytes are converted back to INTEGER(SchemaId) 
10. Schema is requested from the Confluent Schema Registry and using this schema the byteArray is deserialized. 

http://bytepadding.com/big-data/spark/avro/avro-serialization-de-serialization-using-confluent-schema-registry/