AVRO
LA PUISSANCE DU BINAIRE, LA SOUPLESSE
DU JSON
MYSELF
Alexandre Victoor
Architecte à la SGCIB
alexvictoor@gmail.com
https://github.com/alexvictoor
@alex_victoor
Install-Package Microsoft.Hadoop.Avro
UN FICHIER AVRO
           
{
    "type":"record",
    "namespace": "DevoxxFR.Example",
    "name":"Trade",
    "fields":
        [
            { "name":"ClientId", "type":"int" },
            { "name":"Nominal", "type":"double" },
            { "name":"Date", "type":"string" }
        ]
}
         
           
{
    "type":"record",
    "namespace": "DevoxxFR.Example",
    "name":"Trade",
    "fields":
        [
            { "name":"ClientId", "type":"int" },
            { "name":"Nominal", "type":"double" },
            { "name":"Date", "type":"string" },                              
            {
                "name":"product",    
                "type":
                    ["null", {
                        "type":"record",
                        "namespace":"DevoxxFR.Example",
                        "name":"Product",
                        "default":null,
         
           
java ­jar avro­tools.jar compile schema trade.avro
         
AVEC UN SEUL OBJECT
           
DatumWriter<Trade> writer = new SpecificDatumWriter<Trade>();
         
           
encoder = EncoderFactory.get().binaryEncoder(outputStream, null);
         
           
writer.write(trade, encoder);
         
PUIS POUR LIRE
           
DatumReader<Trade> reader = new SpecificDatumReader<Trade>();
         
           
decoder = DecoderFactory.get().binaryDecoder(inputStream, null);
         
           
trade = reader.read(null, decoder);
         
SANS GÉNÉRATION
           
GenericRecord record = new GenericData.Record(SCHEMA);
record.put("ProductId", 123);
record.put("Nominal", 42000);
         
           
DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>(SCHEMA
         
           
DatumReader<GenericRecord> datumReader = new GenericDatumReader<>(SCHEMA
         
ECRIRE EN MASSE
ECRIRE EN MASSE
           
File avroDataFile; // on peut aussi utiliser un OutputStream
  
         
ECRIRE EN MASSE
           
File avroDataFile; // on peut aussi utiliser un OutputStream
DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>();
 
         
ECRIRE EN MASSE
           
File avroDataFile; // on peut aussi utiliser un OutputStream
DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>();
DataFileWriter<GenericRecord> dataFileWriter 
     = new DataFileWriter<>(datumWriter);
 
         
ECRIRE EN MASSE
           
File avroDataFile; // on peut aussi utiliser un OutputStream
DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>();
DataFileWriter<GenericRecord> dataFileWriter 
     = new DataFileWriter<>(datumWriter);
dataFileWriter.setCodec(CodecFactory.snappyCodec());
 
         
ECRIRE EN MASSE
           
File avroDataFile; // on peut aussi utiliser un OutputStream
DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>();
DataFileWriter<GenericRecord> dataFileWriter 
     = new DataFileWriter<>(datumWriter);
dataFileWriter.setCodec(CodecFactory.snappyCodec());
dataFileWriter.create(TRADE_SCHEMA, avroDataFile); 
 
         
ECRIRE EN MASSE
           
File avroDataFile; // on peut aussi utiliser un OutputStream
DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>();
DataFileWriter<GenericRecord> dataFileWriter 
     = new DataFileWriter<>(datumWriter);
dataFileWriter.setCodec(CodecFactory.snappyCodec());
dataFileWriter.create(TRADE_SCHEMA, avroDataFile);
for (GenericRecord record : records) {
  dataFileWriter.append(record);
}
         
ET POUR LIRE ?
ET POUR LIRE ?
           
File avroDataFile; // on peut aussi utiliser un InputStream
 
         
ET POUR LIRE ?
           
File avroDataFile; // on peut aussi utiliser un InputStream
DatumReader<GenericRecord> datumReader = new GenericDatumReader<>();
 
         
ET POUR LIRE ?
           
File avroDataFile; // on peut aussi utiliser un InputStream
DatumReader<GenericRecord> datumReader = new GenericDatumReader<>();
DataFileReader<GenericRecord> dataFileReader 
    = new DataFileReader(avroDataFile, datumReader);
 
         
ET POUR LIRE ?
           
File avroDataFile; // on peut aussi utiliser un InputStream
DatumReader<GenericRecord> datumReader = new GenericDatumReader<>();
DataFileReader<GenericRecord> dataFileReader 
    = new DataFileReader(avroDataFile, datumReader);
for (GenericRecord record : dataFileReader) {
  // traitement sur chaque record
}
         
C'EST BIEN MAIS...
           
{
    "type":"record",
    "namespace": "DevoxxFR.Example",
    "name":"Trade",
    "fields":
        [
            { "name":"ClientId", "type":"int" },
            { "name":"Nominal", "type":"double" },
            { "name":"Date", "type":"string" },                              
            {
                "name":"product",    
                "type":
                    ["null", {
                        "type":"record",
                        "namespace": "DevoxxFR.Example",
                        "name":"Product",
            "default":null,
         
LA KILLER FEATURE
           
// la résolution de schema
new GenericDatumReader(writerSchema, readerSchema)
Writer Schema
Le schéma qui a été utilisé pour sérialiser
LA KILLER FEATURE
           
// la résolution de schema
new GenericDatumReader(writerSchema, readerSchema)
Reader Schema
Les données dont vous avez besoin
ENTRE 2 SCHEMAS, ON PEUT
- ajouter un champ
- supprimer un champ
- renommer un champ (avec un alias)
On ne peut pas changer le type d'un champ
COMPATIBLES ?
 
 
SchemaCompatibility
  .checkReaderWriterCompatibility(readerSchema, writerSchema)
D'AUTRES USAGES
- Event sourcing
- Echanges de messages entre applications
EVENT SOURCING
EVENT SOURCING
DEMO
TRADE
productId
quantity
nominal
date
TRADE
productId
quantity
nominal
date
tradingPlace
RESSOURCES
Ces slides :
Une variante "alt.net" de cette prez :
La spec avro :
Le tuto MS :
Le SDK MS Hadoop :
https://github.com/alexvictoor/AvroDevoxxFr
https://github.com/alexvictoor/AvroAltNet
http://avro.apache.org/docs/1.7.7/spec.html
http://bit.ly/1uYRX3I
http://hadoopsdk.codeplex.com/SourceControl/latest

Avro, la puissance du binaire, la souplesse du JSON

  • 1.
    AVRO LA PUISSANCE DUBINAIRE, LA SOUPLESSE DU JSON
  • 2.
    MYSELF Alexandre Victoor Architecte àla SGCIB alexvictoor@gmail.com https://github.com/alexvictoor @alex_victoor
  • 4.
  • 6.
  • 7.
               {     "type":"record",     "namespace": "DevoxxFR.Example",     "name":"Trade",     "fields":         [             { "name":"ClientId", "type":"int" },             { "name":"Nominal", "type":"double" },             { "name":"Date", "type":"string" }         ] }          
  • 8.
               {     "type":"record",     "namespace": "DevoxxFR.Example",     "name":"Trade",     "fields":         [             { "name":"ClientId", "type":"int" },             { "name":"Nominal", "type":"double" },             { "name":"Date", "type":"string" },                                           {                 "name":"product",                     "type":                     ["null", {                         "type":"record",                         "namespace":"DevoxxFR.Example",                         "name":"Product",                         "default":null,          
  • 9.
               java ­jar avro­tools.jar compile schema trade.avro          
  • 10.
    AVEC UN SEULOBJECT             DatumWriter<Trade> writer = new SpecificDatumWriter<Trade>();                       encoder = EncoderFactory.get().binaryEncoder(outputStream, null);                       writer.write(trade, encoder);          
  • 11.
    PUIS POUR LIRE            DatumReader<Trade> reader = new SpecificDatumReader<Trade>();                       decoder = DecoderFactory.get().binaryDecoder(inputStream, null);                       trade = reader.read(null, decoder);          
  • 12.
    SANS GÉNÉRATION            GenericRecord record = new GenericData.Record(SCHEMA); record.put("ProductId", 123); record.put("Nominal", 42000);                       DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>(SCHEMA                       DatumReader<GenericRecord> datumReader = new GenericDatumReader<>(SCHEMA          
  • 13.
  • 14.
    ECRIRE EN MASSE            File avroDataFile; // on peut aussi utiliser un OutputStream             
  • 15.
    ECRIRE EN MASSE            File avroDataFile; // on peut aussi utiliser un OutputStream DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>();            
  • 16.
    ECRIRE EN MASSE            File avroDataFile; // on peut aussi utiliser un OutputStream DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>(); DataFileWriter<GenericRecord> dataFileWriter       = new DataFileWriter<>(datumWriter);            
  • 17.
    ECRIRE EN MASSE            File avroDataFile; // on peut aussi utiliser un OutputStream DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>(); DataFileWriter<GenericRecord> dataFileWriter       = new DataFileWriter<>(datumWriter); dataFileWriter.setCodec(CodecFactory.snappyCodec());            
  • 18.
    ECRIRE EN MASSE            File avroDataFile; // on peut aussi utiliser un OutputStream DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>(); DataFileWriter<GenericRecord> dataFileWriter       = new DataFileWriter<>(datumWriter); dataFileWriter.setCodec(CodecFactory.snappyCodec()); dataFileWriter.create(TRADE_SCHEMA, avroDataFile);             
  • 19.
    ECRIRE EN MASSE            File avroDataFile; // on peut aussi utiliser un OutputStream DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>(); DataFileWriter<GenericRecord> dataFileWriter       = new DataFileWriter<>(datumWriter); dataFileWriter.setCodec(CodecFactory.snappyCodec()); dataFileWriter.create(TRADE_SCHEMA, avroDataFile); for (GenericRecord record : records) {   dataFileWriter.append(record); }          
  • 20.
  • 21.
    ET POUR LIRE?             File avroDataFile; // on peut aussi utiliser un InputStream            
  • 22.
    ET POUR LIRE?             File avroDataFile; // on peut aussi utiliser un InputStream DatumReader<GenericRecord> datumReader = new GenericDatumReader<>();            
  • 23.
    ET POUR LIRE?             File avroDataFile; // on peut aussi utiliser un InputStream DatumReader<GenericRecord> datumReader = new GenericDatumReader<>(); DataFileReader<GenericRecord> dataFileReader      = new DataFileReader(avroDataFile, datumReader);            
  • 24.
    ET POUR LIRE?             File avroDataFile; // on peut aussi utiliser un InputStream DatumReader<GenericRecord> datumReader = new GenericDatumReader<>(); DataFileReader<GenericRecord> dataFileReader      = new DataFileReader(avroDataFile, datumReader); for (GenericRecord record : dataFileReader) {   // traitement sur chaque record }          
  • 25.
    C'EST BIEN MAIS...            {     "type":"record",     "namespace": "DevoxxFR.Example",     "name":"Trade",     "fields":         [             { "name":"ClientId", "type":"int" },             { "name":"Nominal", "type":"double" },             { "name":"Date", "type":"string" },                                           {                 "name":"product",                     "type":                     ["null", {                         "type":"record",                         "namespace": "DevoxxFR.Example",                         "name":"Product",             "default":null,          
  • 27.
    LA KILLER FEATURE            // la résolution de schema new GenericDatumReader(writerSchema, readerSchema) Writer Schema Le schéma qui a été utilisé pour sérialiser
  • 28.
    LA KILLER FEATURE            // la résolution de schema new GenericDatumReader(writerSchema, readerSchema) Reader Schema Les données dont vous avez besoin
  • 29.
    ENTRE 2 SCHEMAS,ON PEUT - ajouter un champ - supprimer un champ - renommer un champ (avec un alias) On ne peut pas changer le type d'un champ
  • 30.
  • 31.
    D'AUTRES USAGES - Eventsourcing - Echanges de messages entre applications
  • 32.
  • 33.
  • 34.
  • 38.
    RESSOURCES Ces slides : Unevariante "alt.net" de cette prez : La spec avro : Le tuto MS : Le SDK MS Hadoop : https://github.com/alexvictoor/AvroDevoxxFr https://github.com/alexvictoor/AvroAltNet http://avro.apache.org/docs/1.7.7/spec.html http://bit.ly/1uYRX3I http://hadoopsdk.codeplex.com/SourceControl/latest