AVRO - Guida rapida

Per trasferire i dati su una rete o per la loro archiviazione persistente, è necessario serializzare i dati. Prima delserialization APIs fornito da Java e Hadoop, abbiamo un'utilità speciale, chiamata Avro, una tecnica di serializzazione basata su schema.

Questo tutorial ti insegna come serializzare e deserializzare i dati utilizzando Avro. Avro fornisce librerie per vari linguaggi di programmazione. In questo tutorial, dimostriamo gli esempi utilizzando la libreria Java.

Cos'è Avro?

Apache Avro è un sistema di serializzazione dei dati indipendente dalla lingua. È stato sviluppato da Doug Cutting, il padre di Hadoop. Poiché le classi scrivibili Hadoop mancano di portabilità della lingua, Avro diventa molto utile, poiché si occupa di formati di dati che possono essere elaborati da più lingue. Avro è uno strumento preferito per serializzare i dati in Hadoop.

Avro ha un sistema basato su schema. Uno schema indipendente dalla lingua è associato alle sue operazioni di lettura e scrittura. Avro serializza i dati che hanno uno schema integrato. Avro serializza i dati in un formato binario compatto, che può essere deserializzato da qualsiasi applicazione.

Avro utilizza il formato JSON per dichiarare le strutture di dati. Attualmente supporta linguaggi come Java, C, C ++, C #, Python e Ruby.

Schemi Avro

Avro dipende molto da esso schema. Consente la scrittura di tutti i dati senza alcuna conoscenza preliminare dello schema. Serializza rapidamente e i dati serializzati risultanti sono di dimensioni inferiori. Lo schema viene archiviato insieme ai dati Avro in un file per qualsiasi ulteriore elaborazione.

In RPC, il client e il server si scambiano gli schemi durante la connessione. Questo scambio aiuta nella comunicazione tra campi con lo stesso nome, campi mancanti, campi extra, ecc.

Gli schemi Avro sono definiti con JSON che ne semplifica l'implementazione nei linguaggi con librerie JSON.

Come Avro, ci sono altri meccanismi di serializzazione in Hadoop come Sequence Files, Protocol Buffers, e Thrift.

Confronto con parsimonia e buffer di protocollo

Thrift e Protocol Bufferssono le biblioteche più competenti con Avro. Avro differisce da questi framework nei seguenti modi:

  • Avro supporta i tipi dinamici e statici secondo il requisito. I buffer di protocollo e il risparmio utilizzano i linguaggi di definizione dell'interfaccia (IDL) per specificare gli schemi e i loro tipi. Questi IDL vengono utilizzati per generare codice per la serializzazione e la deserializzazione.

  • Avro è integrato nell'ecosistema Hadoop. I buffer parsimoniosi e di protocollo non sono costruiti nell'ecosistema Hadoop.

A differenza di Thrift e Protocol Buffer, la definizione dello schema di Avro è in JSON e non in alcun IDL proprietario.

Proprietà Avro Risparmio e tampone di protocollo
Schema dinamico No
Integrato in Hadoop No
Schema in JSON No
Non c'è bisogno di compilare No
Non c'è bisogno di dichiarare ID No
Bleeding edge No

Caratteristiche di Avro

Di seguito sono elencate alcune delle caratteristiche principali di Avro:

  • Avro è un language-neutral sistema di serializzazione dei dati.

  • Può essere elaborato da molti linguaggi (attualmente C, C ++, C #, Java, Python e Ruby).

  • Avro crea un formato strutturato binario che è entrambe le cose compressible e splittable. Quindi può essere utilizzato in modo efficiente come input per i lavori di Hadoop MapReduce.

  • Avro fornisce rich data structures. Ad esempio, puoi creare un record che contiene una matrice, un tipo enumerato e un sub record. Questi tipi di dati possono essere creati in qualsiasi lingua, possono essere elaborati in Hadoop e i risultati possono essere inviati a una terza lingua.

  • Avro schemas definito in JSON, facilita l'implementazione nei linguaggi che dispongono già di librerie JSON.

  • Avro crea un file autodescrittivo denominato Avro Data File, in cui archivia i dati insieme al relativo schema nella sezione dei metadati.

  • Avro viene utilizzato anche nelle chiamate di procedura remota (RPC). Durante RPC, client e server si scambiano schemi nell'handshake di connessione.

Funzionamento generale di Avro

Per utilizzare Avro, è necessario seguire il flusso di lavoro indicato:

  • Step 1- Crea schemi. Qui devi progettare lo schema Avro in base ai tuoi dati.

  • Step 2- Leggi gli schemi nel tuo programma. È fatto in due modi:

    • By Generating a Class Corresponding to Schema- Compilare lo schema utilizzando Avro. Questo genera un file di classe corrispondente allo schema

    • By Using Parsers Library - È possibile leggere direttamente lo schema utilizzando la libreria dei parser.

  • Step 3 - Serializzare i dati utilizzando l'API di serializzazione fornita per Avro, che si trova nel file package org.apache.avro.specific.

  • Step 4 - Deserializzare i dati utilizzando l'API di deserializzazione fornita per Avro, che si trova nel file package org.apache.avro.specific.

I dati vengono serializzati per due obiettivi:

  • Per l'archiviazione persistente

  • Per trasportare i dati sulla rete

Cos'è la serializzazione?

La serializzazione è il processo di traduzione delle strutture di dati o dello stato degli oggetti in forma binaria o testuale per trasportare i dati sulla rete o per archiviarli in una memoria persistente. Una volta che i dati sono stati trasportati sulla rete o recuperati dalla memoria persistente, devono essere nuovamente deserializzati. La serializzazione è definita comemarshalling e la deserializzazione è definita come unmarshalling.

Serializzazione in Java

Java fornisce un meccanismo, chiamato object serialization dove un oggetto può essere rappresentato come una sequenza di byte che include i dati dell'oggetto nonché le informazioni sul tipo di oggetto e sui tipi di dati memorizzati nell'oggetto.

Dopo che un oggetto serializzato è stato scritto in un file, può essere letto dal file e deserializzato. Ovvero, le informazioni sul tipo e i byte che rappresentano l'oggetto ei suoi dati possono essere utilizzati per ricreare l'oggetto in memoria.

ObjectInputStream e ObjectOutputStream le classi vengono utilizzate rispettivamente per serializzare e deserializzare un oggetto in Java.

Serializzazione in Hadoop

Generalmente nei sistemi distribuiti come Hadoop, viene utilizzato il concetto di serializzazione Interprocess Communication e Persistent Storage.

Comunicazione tra processi

  • Per stabilire la comunicazione interprocesso tra i nodi collegati in una rete, è stata utilizzata la tecnica RPC.

  • RPC ha utilizzato la serializzazione interna per convertire il messaggio in formato binario prima di inviarlo al nodo remoto tramite la rete. All'altra estremità il sistema remoto deserializza il flusso binario nel messaggio originale.

  • Il formato di serializzazione RPC deve essere il seguente:

    • Compact - Per utilizzare al meglio la larghezza di banda della rete, che è la risorsa più scarsa in un data center.

    • Fast - Poiché la comunicazione tra i nodi è cruciale nei sistemi distribuiti, il processo di serializzazione e deserializzazione dovrebbe essere veloce, producendo meno overhead.

    • Extensible - I protocolli cambiano nel tempo per soddisfare i nuovi requisiti, quindi dovrebbe essere semplice evolvere il protocollo in modo controllato per client e server.

    • Interoperable - Il formato del messaggio dovrebbe supportare i nodi scritti in lingue diverse.

Archiviazione persistente

Persistent Storage è una struttura di archiviazione digitale che non perde i dati con la perdita di alimentazione. File, cartelle, database sono esempi di archiviazione persistente.

Interfaccia scrivibile

Questa è l'interfaccia in Hadoop che fornisce metodi per la serializzazione e la deserializzazione. La tabella seguente descrive i metodi:

S.No. Metodi e descrizione
1

void readFields(DataInput in)

Questo metodo viene utilizzato per deserializzare i campi dell'oggetto specificato.

2

void write(DataOutput out)

Questo metodo viene utilizzato per serializzare i campi dell'oggetto specificato.

Interfaccia comparabile scrivibile

È la combinazione di Writable e Comparableinterfacce. Questa interfaccia ereditaWritable interfaccia di Hadoop così come Comparableinterfaccia di Java. Pertanto fornisce metodi per la serializzazione, la deserializzazione e il confronto dei dati.

S.No. Metodi e descrizione
1

int compareTo(class obj)

Questo metodo confronta l'oggetto corrente con l'oggetto dato obj.

Oltre a queste classi, Hadoop supporta una serie di classi wrapper che implementano l'interfaccia WritableComparable. Ogni classe racchiude un tipo primitivo Java. La gerarchia delle classi della serializzazione Hadoop è riportata di seguito:

Queste classi sono utili per serializzare vari tipi di dati in Hadoop. Ad esempio, consideriamo ilIntWritableclasse. Vediamo come viene usata questa classe per serializzare e deserializzare i dati in Hadoop.

Classe IntWritable

Questa classe implementa Writable, Comparable, e WritableComparableinterfacce. Avvolge un tipo di dati intero in esso. Questa classe fornisce metodi utilizzati per serializzare e deserializzare il tipo intero di dati.

Costruttori

S.No. Sommario
1 IntWritable()
2 IntWritable( int value)

Metodi

S.No. Sommario
1

int get()

Utilizzando questo metodo è possibile ottenere il valore intero presente nell'oggetto corrente.

2

void readFields(DataInput in)

Questo metodo viene utilizzato per deserializzare i dati nel file DataInput oggetto.

3

void set(int value)

Questo metodo viene utilizzato per impostare il valore della corrente IntWritable oggetto.

4

void write(DataOutput out)

Questo metodo viene utilizzato per serializzare i dati nell'oggetto corrente nel dato DataOutput oggetto.

Serializzazione dei dati in Hadoop

La procedura per serializzare il tipo intero di dati è discussa di seguito.

  • Istanziare IntWritable class inserendo un valore intero al suo interno.

  • Istanziare ByteArrayOutputStream classe.

  • Istanziare DataOutputStream class e passare l'oggetto di ByteArrayOutputStream classe ad esso.

  • Serializza il valore intero nell'oggetto IntWritable utilizzando write()metodo. Questo metodo richiede un oggetto della classe DataOutputStream.

  • I dati serializzati verranno memorizzati nell'oggetto array di byte che viene passato come parametro al file DataOutputStreamclasse al momento dell'istanziazione. Converti i dati nell'oggetto in array di byte.

Esempio

L'esempio seguente mostra come serializzare i dati di tipo intero in Hadoop:

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;

import java.io.IOException;

import org.apache.hadoop.io.IntWritable;

public class Serialization {
   public byte[] serialize() throws IOException{
		
      //Instantiating the IntWritable object
      IntWritable intwritable = new IntWritable(12);
   
      //Instantiating ByteArrayOutputStream object
      ByteArrayOutputStream byteoutputStream = new ByteArrayOutputStream();
   
      //Instantiating DataOutputStream object
      DataOutputStream dataOutputStream = new
      DataOutputStream(byteoutputStream);
   
      //Serializing the data
      intwritable.write(dataOutputStream);
   
      //storing the serialized object in bytearray
      byte[] byteArray = byteoutputStream.toByteArray();
   
      //Closing the OutputStream
      dataOutputStream.close();
      return(byteArray);
   }
	
   public static void main(String args[]) throws IOException{
      Serialization serialization= new Serialization();
      serialization.serialize();
      System.out.println();
   }
}

Deserializzazione dei dati in Hadoop

La procedura per deserializzare il tipo intero di dati è discussa di seguito:

  • Istanziare IntWritable class inserendo un valore intero al suo interno.

  • Istanziare ByteArrayOutputStream classe.

  • Istanziare DataOutputStream class e passare l'oggetto di ByteArrayOutputStream classe ad esso.

  • Deserializza i dati nell'oggetto di DataInputStream utilizzando readFields() metodo della classe IntWritable.

  • I dati deserializzati verranno archiviati nell'oggetto della classe IntWritable. Puoi recuperare questi dati usandoget() metodo di questa classe.

Esempio

L'esempio seguente mostra come deserializzare i dati di tipo intero in Hadoop:

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;

import org.apache.hadoop.io.IntWritable;

public class Deserialization {

   public void deserialize(byte[]byteArray) throws Exception{
   
      //Instantiating the IntWritable class
      IntWritable intwritable =new IntWritable();
      
      //Instantiating ByteArrayInputStream object
      ByteArrayInputStream InputStream = new ByteArrayInputStream(byteArray);
      
      //Instantiating DataInputStream object
      DataInputStream datainputstream=new DataInputStream(InputStream);
      
      //deserializing the data in DataInputStream
      intwritable.readFields(datainputstream);
      
      //printing the serialized data
      System.out.println((intwritable).get());
   }
   
   public static void main(String args[]) throws Exception {
      Deserialization dese = new Deserialization();
      dese.deserialize(new Serialization().serialize());
   }
}

Vantaggio di Hadoop rispetto alla serializzazione Java

La serializzazione basata su scrivibili di Hadoop è in grado di ridurre il sovraccarico per la creazione di oggetti riutilizzando gli oggetti scrivibili, il che non è possibile con il framework di serializzazione nativo di Java.

Svantaggi della serializzazione Hadoop

Per serializzare i dati di Hadoop, esistono due modi:

  • Puoi usare il file Writable classi, fornite dalla libreria nativa di Hadoop.

  • Puoi anche usare Sequence Files che memorizzano i dati in formato binario.

Lo svantaggio principale di questi due meccanismi è quello Writables e SequenceFiles hanno solo un'API Java e non possono essere scritti o letti in nessun altro linguaggio.

Pertanto nessuno dei file creati in Hadoop con i due meccanismi di cui sopra non può essere letto da qualsiasi altra terza lingua, il che rende Hadoop una scatola limitata. Per risolvere questo inconveniente, Doug Cutting ha creatoAvro, il quale è un language independent data structure.

La fondazione software Apache fornisce ad Avro varie versioni. È possibile scaricare la versione richiesta dai mirror di Apache. Vediamo come configurare l'ambiente per lavorare con Avro -

Download di Avro

Per scaricare Apache Avro, procedere con quanto segue:

  • Apri la pagina web Apache.org . Vedrai la homepage di Apache Avro come mostrato di seguito -

  • Fare clic su progetto → versioni. Otterrai un elenco di versioni.

  • Seleziona l'ultima versione che ti porta a un link per il download.

  • mirror.nexcess è uno dei collegamenti in cui è possibile trovare l'elenco di tutte le librerie di diverse lingue supportate da Avro come mostrato di seguito:

È possibile selezionare e scaricare la libreria per una qualsiasi delle lingue fornite. In questo tutorial, utilizziamo Java. Quindi scarica i file jaravro-1.7.7.jar e avro-tools-1.7.7.jar.

Avro con Eclipse

Per utilizzare Avro in ambiente Eclipse, è necessario seguire i passaggi indicati di seguito:

  • Step 1. Apri eclipse.

  • Step 2. Crea un progetto.

  • Step 3.Fare clic con il tasto destro sul nome del progetto. Otterrai un menu di scelta rapida.

  • Step 4. Clicca su Build Path. Ti porta a un altro menu di scelta rapida.

  • Step 5. Clicca su Configure Build Path... Puoi vedere la finestra Proprietà del tuo progetto come mostrato di seguito -

  • Step 6. Nella scheda librerie, fare clic su ADD EXternal JARs... pulsante.

  • Step 7. Seleziona il file jar avro-1.77.jar hai scaricato.

  • Step 8. Clicca su OK.

Avro con Maven

Puoi anche ottenere la libreria Avro nel tuo progetto usando Maven. Di seguito è riportato il file pom.xml per Avro.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="   http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

   <modelVersion>4.0.0</modelVersion>
   <groupId>Test</groupId>
   <artifactId>Test</artifactId>
   <version>0.0.1-SNAPSHOT</version>

   <build>
      <sourceDirectory>src</sourceDirectory>
      <plugins>
         <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
		
            <configuration>
               <source>1.7</source>
               <target>1.7</target>
            </configuration>
		
         </plugin>
      </plugins>
   </build>

   <dependencies>
      <dependency>
         <groupId>org.apache.avro</groupId>
         <artifactId>avro</artifactId>
         <version>1.7.7</version>
      </dependency>
	
      <dependency>
         <groupId>org.apache.avro</groupId>
         <artifactId>avro-tools</artifactId>
         <version>1.7.7</version>
      </dependency>
	
      <dependency>
         <groupId>org.apache.logging.log4j</groupId>
         <artifactId>log4j-api</artifactId>
         <version>2.0-beta9</version>
      </dependency>
	
      <dependency>
         <groupId>org.apache.logging.log4j</groupId>
         <artifactId>log4j-core</artifactId>
         <version>2.0-beta9</version>
      </dependency>
	
   </dependencies>

</project>

Impostazione del percorso di classe

Per lavorare con Avro in ambiente Linux, scarica i seguenti file jar:

  • avro-1.77.jar
  • avro-tools-1.77.jar
  • log4j-api-2.0-beta9.jar
  • og4j-core-2.0.beta9.jar.

Copia questi file in una cartella e imposta il percorso di classe nella cartella, nel file./bashrc file come mostrato di seguito.

#class path for Avro
export CLASSPATH=$CLASSPATH://home/Hadoop/Avro_Work/jars/*

Avro, essendo un'utilità di serializzazione basata su schema, accetta schemi come input. Nonostante siano disponibili vari schemi, Avro segue i propri standard di definizione degli schemi. Questi schemi descrivono i seguenti dettagli:

  • tipo di file (record per impostazione predefinita)
  • luogo di registrazione
  • nome del record
  • campi del record con i corrispondenti tipi di dati

Utilizzando questi schemi, è possibile memorizzare i valori serializzati in formato binario utilizzando meno spazio. Questi valori vengono archiviati senza metadati.

Creazione di schemi Avro

Lo schema Avro viene creato nel formato di documento JavaScript Object Notation (JSON), che è un formato di interscambio di dati basato su testo leggero. Viene creato in uno dei seguenti modi:

  • Una stringa JSON
  • Un oggetto JSON
  • Un array JSON

Example - L'esempio seguente mostra uno schema, che definisce un documento, sotto lo spazio dei nomi Tutorialspoint, con nome Employee, con campi name ed age.

{
   "type" : "record",
   "namespace" : "Tutorialspoint",
   "name" : "Employee",
   "fields" : [
      { "name" : "Name" , "type" : "string" },
      { "name" : "Age" , "type" : "int" }
   ]
}

In questo esempio, puoi osservare che ci sono quattro campi per ogni record:

  • type - Questo campo si trova sotto il documento e sotto il campo denominato campi.

    • In caso di documento, mostra il tipo di documento, generalmente un record perché ci sono più campi.

    • Quando è campo, il tipo descrive il tipo di dati.

  • namespace - Questo campo descrive il nome dello spazio dei nomi in cui risiede l'oggetto.

  • name - Questo campo si trova sotto il documento e sotto il campo denominato campi.

    • In caso di documento, descrive il nome dello schema. Questo nome dello schema insieme allo spazio dei nomi identifica in modo univoco lo schema all'interno del negozio (Namespace.schema name). Nell'esempio precedente, il nome completo dello schema sarà Tutorialspoint.Employee.

    • In caso di campi, descrive il nome del campo.

Tipi di dati primitivi di Avro

Lo schema Avro ha tipi di dati primitivi e tipi di dati complessi. La tabella seguente descrive ilprimitive data types di Avro -

Tipo di dati Descrizione
nullo Null è un tipo senza valore.
int Intero con segno a 32 bit.
lungo Intero con segno a 64 bit.
galleggiante numero a virgola mobile IEEE 754 a precisione singola (32 bit).
Doppio numero a virgola mobile IEEE 754 a doppia precisione (64 bit).
byte sequenza di byte senza segno a 8 bit.
corda Sequenza di caratteri Unicode.

Tipi di dati complessi di Avro

Insieme ai tipi di dati primitivi, Avro fornisce sei tipi di dati complessi: Record, Enums, Arrays, Maps, Unions e Fixed.

Disco

Un tipo di dati record in Avro è una raccolta di più attributi. Supporta i seguenti attributi:

  • name - Il valore di questo campo contiene il nome del record.

  • namespace - Il valore di questo campo contiene il nome dello spazio dei nomi in cui è archiviato l'oggetto.

  • type - Il valore di questo attributo contiene il tipo di documento (record) o il tipo di dati del campo nello schema.

  • fields - Questo campo contiene un array JSON, che contiene l'elenco di tutti i campi nello schema, ciascuno con il nome e gli attributi del tipo.

Example

Di seguito è riportato l'esempio di un record.

{
" type " : "record",
" namespace " : "Tutorialspoint",
" name " : "Employee",
" fields " : [
 { "name" : " Name" , "type" : "string" },
 { "name" : "age" , "type" : "int" }
 ]
}

Enum

Un'enumerazione è un elenco di elementi in una raccolta, l'enumerazione Avro supporta i seguenti attributi:

  • name - Il valore di questo campo contiene il nome dell'enumerazione.

  • namespace - Il valore di questo campo contiene la stringa che qualifica il nome dell'Enumerazione.

  • symbols - Il valore di questo campo contiene i simboli dell'enumerazione come un array di nomi.

Example

Di seguito è riportato l'esempio di un'enumerazione.

{
   "type" : "enum",
   "name" : "Numbers", 
   "namespace": "data", 
   "symbols" : [ "ONE", "TWO", "THREE", "FOUR" ]
}

Arrays

Questo tipo di dati definisce un campo array con un singolo elemento attributo. Questo attributo items specifica il tipo di elementi nell'array.

Example

{ " type " : " array ", " items " : " int " }

Mappe

Il tipo di dati della mappa è un array di coppie chiave-valore, organizza i dati come coppie chiave-valore. La chiave per una mappa Avro deve essere una stringa. I valori di una mappa contengono il tipo di dati del contenuto della mappa.

Example

{"type" : "map", "values" : "int"}

Sindacati

Un tipo di dati unione viene utilizzato ogni volta che il campo ha uno o più tipi di dati. Sono rappresentati come array JSON. Ad esempio, se un campo può essere int o null, l'unione viene rappresentata come ["int", "null"].

Example

Di seguito è riportato un documento di esempio che utilizza i sindacati:

{ 
   "type" : "record", 
   "namespace" : "tutorialspoint", 
   "name" : "empdetails ", 
   "fields" : 
   [ 
      { "name" : "experience", "type": ["int", "null"] }, { "name" : "age", "type": "int" } 
   ] 
}

Fisso

Questo tipo di dati viene utilizzato per dichiarare un campo di dimensioni fisse che può essere utilizzato per memorizzare dati binari. Ha il nome del campo e i dati come attributi. Il nome contiene il nome del campo e la dimensione contiene la dimensione del campo.

Example

{ "type" : "fixed" , "name" : "bdata", "size" : 1048576}

Nel capitolo precedente abbiamo descritto il tipo di input di Avro, ovvero gli schemi Avro. In questo capitolo verranno illustrate le classi ei metodi utilizzati nella serializzazione e deserializzazione degli schemi Avro.

SpecificDatumWriter Classe

Questa classe appartiene al pacchetto org.apache.avro.specific. Implementa ilDatumWriter interfaccia che converte gli oggetti Java in un formato serializzato in memoria.

Costruttore

S.No. Descrizione
1 SpecificDatumWriter(Schema schema)

Metodo

S.No. Descrizione
1

SpecificData getSpecificData()

Restituisce l'implementazione SpecificData utilizzata da questo writer.

SpecificDatumReader Classe

Questa classe appartiene al pacchetto org.apache.avro.specific. Implementa ilDatumReader interfaccia che legge i dati di uno schema e determina la rappresentazione dei dati in memoria. SpecificDatumReader è la classe che supporta le classi java generate.

Costruttore

S.No. Descrizione
1

SpecificDatumReader(Schema schema)

Costruisci dove gli schemi dello scrittore e del lettore sono gli stessi.

Metodi

S.No. Descrizione
1

SpecificData getSpecificData()

Restituisce l'oggetto SpecificData contenuto.

2

void setSchema(Schema actual)

Questo metodo viene utilizzato per impostare lo schema del writer.

DataFileWriter

Istanzia DataFileWrite per empclasse. Questa classe scrive una sequenza di record serializzati di dati conformi a uno schema, insieme allo schema in un file.

Costruttore

S.No. Descrizione
1 DataFileWriter(DatumWriter<D> dout)

Metodi

S.No Descrizione
1

void append(D datum)

Aggiunge un dato a un file.

2

DataFileWriter<D> appendTo(File file)

Questo metodo viene utilizzato per aprire un writer aggiungendo a un file esistente.

Data FileReader

Questa classe fornisce l'accesso casuale ai file scritti con DataFileWriter. Eredita la classeDataFileStream.

Costruttore

S.No. Descrizione
1 DataFileReader(File file, DatumReader<D> reader))

Metodi

S.No. Descrizione
1

next()

Legge il dato successivo nel file.

2

Boolean hasNext()

Restituisce vero se rimangono più voci in questo file.

Class Schema.parser

Questa classe è un parser per schemi in formato JSON. Contiene metodi per analizzare lo schema. Appartiene aorg.apache.avro pacchetto.

Costruttore

S.No. Descrizione
1 Schema.Parser()

Metodi

S.No. Descrizione
1

parse (File file)

Analizza lo schema fornito nel dato file.

2

parse (InputStream in)

Analizza lo schema fornito nel dato InputStream.

3

parse (String s)

Analizza lo schema fornito nel dato String.

Interfaccia GenricRecord

Questa interfaccia fornisce metodi per accedere ai campi in base al nome e all'indice.

Metodi

S.No. Descrizione
1

Object get(String key)

Restituisce il valore di un campo dato.

2

void put(String key, Object v)

Imposta il valore di un campo dato il suo nome.

Classe GenericData.Record

Costruttore

S.No. Descrizione
1 GenericData.Record(Schema schema)

Metodi

S.No. Descrizione
1

Object get(String key)

Restituisce il valore di un campo del nome specificato.

2

Schema getSchema()

Restituisce lo schema di questa istanza.

3

void put(int i, Object v)

Imposta il valore di un campo in base alla sua posizione nello schema.

4

void put(String key, Object value)

Imposta il valore di un campo dato il suo nome.

È possibile leggere uno schema Avro nel programma generando una classe corrispondente a uno schema o utilizzando la libreria parser. Questo capitolo descrive come leggere lo schemaby generating a class e Serializing i dati utilizzando Avr.

Serializzazione generando una classe

Per serializzare i dati utilizzando Avro, seguire i passaggi indicati di seguito:

  • Scrivi uno schema Avro.

  • Compilare lo schema utilizzando l'utilità Avro. Ottieni il codice Java corrispondente a quello schema.

  • Popolare lo schema con i dati.

  • Serializzalo usando la libreria Avro.

Definizione di uno schema

Supponi di volere uno schema con i seguenti dettagli:

Field Nome id età stipendio indirizzo
type Corda int int int corda

Crea uno schema Avro come mostrato di seguito.

Salvalo come emp.avsc.

{
   "namespace": "tutorialspoint.com",
   "type": "record",
   "name": "emp",
   "fields": [
      {"name": "name", "type": "string"},
      {"name": "id", "type": "int"},
      {"name": "salary", "type": "int"},
      {"name": "age", "type": "int"},
      {"name": "address", "type": "string"}
   ]
}

Compilazione dello schema

Dopo aver creato uno schema Avro, è necessario compilare lo schema creato utilizzando gli strumenti Avro. avro-tools-1.7.7.jar è il barattolo contenente gli strumenti.

Sintassi per compilare uno schema Avro

java -jar <path/to/avro-tools-1.7.7.jar> compile schema <path/to/schema-file> <destination-folder>

Apri il terminale nella cartella home.

Crea una nuova directory per lavorare con Avro come mostrato di seguito -

$ mkdir Avro_Work

Nella directory appena creata, crea tre sottodirectory:

  • Primo nome schema, per posizionare lo schema.

  • Secondo nome with_code_gen, per posizionare il codice generato.

  • Terzo nome jars, per posizionare i file jar.

$ mkdir schema
$ mkdir with_code_gen
$ mkdir jars

Lo screenshot seguente mostra come il tuo Avro_work la cartella dovrebbe apparire come dopo aver creato tutte le directory.

  • Adesso /home/Hadoop/Avro_work/jars/avro-tools-1.7.7.jar è il percorso della directory in cui è stato scaricato il file avro-tools-1.7.7.jar.

  • /home/Hadoop/Avro_work/schema/ è il percorso della directory in cui è archiviato il file di schema emp.avsc.

  • /home/Hadoop/Avro_work/with_code_gen è la directory in cui desideri memorizzare i file di classe generati.

Ora compila lo schema come mostrato di seguito -

$ java -jar /home/Hadoop/Avro_work/jars/avro-tools-1.7.7.jar compile schema /home/Hadoop/Avro_work/schema/emp.avsc /home/Hadoop/Avro/with_code_gen

Dopo la compilazione, nella directory di destinazione viene creato un pacchetto in base allo spazio dei nomi dello schema. All'interno di questo pacchetto, viene creato il codice sorgente Java con il nome dello schema. Questo codice sorgente generato è il codice Java dello schema dato che può essere utilizzato direttamente nelle applicazioni.

Ad esempio, in questo caso un pacchetto / cartella, denominato tutorialspoint viene creato che contiene un'altra cartella denominata com (poiché lo spazio dei nomi è tutorialspoint.com) e al suo interno è possibile osservare il file generato emp.java. La seguente istantanea mostraemp.java -

Questa classe è utile per creare dati secondo lo schema.

La classe generata contiene -

  • Costruttore predefinito e costruttore parametrizzato che accetta tutte le variabili dello schema.
  • I metodi setter e getter per tutte le variabili nello schema.
  • Metodo Get () che restituisce lo schema.
  • Metodi del costruttore.

Creazione e serializzazione dei dati

Prima di tutto, copia il file java generato utilizzato in questo progetto nella directory corrente o importalo da dove si trova.

Ora possiamo scrivere un nuovo file Java e istanziare la classe nel file generato (emp) per aggiungere i dati dei dipendenti allo schema.

Vediamo la procedura per creare i dati secondo lo schema utilizzando apache Avro.

Passo 1

Istanziare il generato emp classe.

emp e1=new emp( );

Passo 2

Utilizzando i metodi setter, inserire i dati del primo impiegato. Ad esempio, abbiamo creato i dettagli del dipendente di nome Omar.

e1.setName("omar");
e1.setAge(21);
e1.setSalary(30000);
e1.setAddress("Hyderabad");
e1.setId(001);

Allo stesso modo, inserisci tutti i dettagli del dipendente utilizzando i metodi setter.

Passaggio 3

Crea un oggetto di DatumWriter interfaccia utilizzando il SpecificDatumWriterclasse. Questo converte gli oggetti Java in un formato serializzato in memoria. L'esempio seguente crea un'istanzaSpecificDatumWriter oggetto di classe per emp classe.

DatumWriter<emp> empDatumWriter = new SpecificDatumWriter<emp>(emp.class);

Passaggio 4

Istanziare DataFileWriter per empclasse. Questa classe scrive una sequenza di record serializzati di dati conformi a uno schema, insieme allo schema stesso, in un file. Questa classe richiede ilDatumWriter oggetto, come parametro per il costruttore.

DataFileWriter<emp> empFileWriter = new DataFileWriter<emp>(empDatumWriter);

Passaggio 5

Apri un nuovo file per memorizzare i dati corrispondenti allo schema specificato utilizzando create()metodo. Questo metodo richiede lo schema e il percorso del file in cui devono essere memorizzati i dati, come parametri.

Nell'esempio seguente, lo schema viene passato utilizzando getSchema() metodo e il file di dati viene memorizzato nel percorso - /home/Hadoop/Avro/serialized_file/emp.avro.

empFileWriter.create(e1.getSchema(),new File("/home/Hadoop/Avro/serialized_file/emp.avro"));

Passaggio 6

Aggiungi tutti i record creati al file utilizzando append() metodo come mostrato di seguito -

empFileWriter.append(e1);
empFileWriter.append(e2);
empFileWriter.append(e3);

Esempio: serializzazione mediante generazione di una classe

Il seguente programma completo mostra come serializzare i dati in un file utilizzando Apache Avro -

import java.io.File;
import java.io.IOException;

import org.apache.avro.file.DataFileWriter;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.specific.SpecificDatumWriter;

public class Serialize {
   public static void main(String args[]) throws IOException{
	
      //Instantiating generated emp class
      emp e1=new emp();
	
      //Creating values according the schema
      e1.setName("omar");
      e1.setAge(21);
      e1.setSalary(30000);
      e1.setAddress("Hyderabad");
      e1.setId(001);
	
      emp e2=new emp();
	
      e2.setName("ram");
      e2.setAge(30);
      e2.setSalary(40000);
      e2.setAddress("Hyderabad");
      e2.setId(002);
	
      emp e3=new emp();
	
      e3.setName("robbin");
      e3.setAge(25);
      e3.setSalary(35000);
      e3.setAddress("Hyderabad");
      e3.setId(003);
	
      //Instantiate DatumWriter class
      DatumWriter<emp> empDatumWriter = new SpecificDatumWriter<emp>(emp.class);
      DataFileWriter<emp> empFileWriter = new DataFileWriter<emp>(empDatumWriter);
	
      empFileWriter.create(e1.getSchema(), new File("/home/Hadoop/Avro_Work/with_code_gen/emp.avro"));
	
      empFileWriter.append(e1);
      empFileWriter.append(e2);
      empFileWriter.append(e3);
	
      empFileWriter.close();
	
      System.out.println("data successfully serialized");
   }
}

Sfoglia la directory in cui si trova il codice generato. In questo caso, ahome/Hadoop/Avro_work/with_code_gen.

In Terminal −

$ cd home/Hadoop/Avro_work/with_code_gen/

In GUI −

Ora copia e salva il programma sopra nel file denominato Serialize.java

Compilalo ed eseguilo come mostrato di seguito -

$ javac Serialize.java
$ java Serialize

Produzione

data successfully serialized

Se verifichi il percorso fornito nel programma, puoi trovare il file serializzato generato come mostrato di seguito.

Come descritto in precedenza, è possibile leggere uno schema Avro in un programma generando una classe corrispondente allo schema o utilizzando la libreria parser. Questo capitolo descrive come leggere lo schemaby generating a class e Deserialize i dati utilizzando Avro.

Deserializzazione generando una classe

I dati serializzati vengono archiviati nel file emp.avro. Puoi deserializzarlo e leggerlo utilizzando Avro.

Seguire la procedura indicata di seguito per deserializzare i dati serializzati da un file.

Passo 1

Crea un oggetto di DatumReader interfaccia utilizzando SpecificDatumReader classe.

DatumReader<emp>empDatumReader = new SpecificDatumReader<emp>(emp.class);

Passo 2

Istanziare DataFileReader per empclasse. Questa classe legge i dati serializzati da un file. Richiede ilDataumeader oggetto e percorso del file in cui sono presenti i dati serializzati, come parametri per il costruttore.

DataFileReader<emp> dataFileReader = new DataFileReader(new File("/path/to/emp.avro"), empDatumReader);

Passaggio 3

Stampare i dati deserializzati, utilizzando i metodi di DataFileReader.

  • Il hasNext() restituirà un valore booleano se sono presenti elementi nel lettore.

  • Il next() metodo di DataFileReader restituisce i dati nel lettore.

while(dataFileReader.hasNext()){

   em=dataFileReader.next(em);
   System.out.println(em);
}

Esempio: deserializzazione mediante generazione di una classe

Il seguente programma completo mostra come deserializzare i dati in un file utilizzando Avro.

import java.io.File;
import java.io.IOException;

import org.apache.avro.file.DataFileReader;
import org.apache.avro.io.DatumReader;
import org.apache.avro.specific.SpecificDatumReader;

public class Deserialize {
   public static void main(String args[]) throws IOException{
	
      //DeSerializing the objects
      DatumReader<emp> empDatumReader = new SpecificDatumReader<emp>(emp.class);
		
      //Instantiating DataFileReader
      DataFileReader<emp> dataFileReader = new DataFileReader<emp>(new
         File("/home/Hadoop/Avro_Work/with_code_genfile/emp.avro"), empDatumReader);
      emp em=null;
		
      while(dataFileReader.hasNext()){
      
         em=dataFileReader.next(em);
         System.out.println(em);
      }
   }
}

Sfoglia nella directory in cui è posizionato il codice generato. In questo caso, ahome/Hadoop/Avro_work/with_code_gen.

$ cd home/Hadoop/Avro_work/with_code_gen/

Ora copia e salva il programma sopra nel file denominato DeSerialize.java. Compilalo ed eseguilo come mostrato di seguito -

$ javac Deserialize.java
$ java Deserialize

Produzione

{"name": "omar", "id": 1, "salary": 30000, "age": 21, "address": "Hyderabad"}
{"name": "ram", "id": 2, "salary": 40000, "age": 30, "address": "Hyderabad"}
{"name": "robbin", "id": 3, "salary": 35000, "age": 25, "address": "Hyderabad"}

È possibile leggere uno schema Avro in un programma generando una classe corrispondente a uno schema o utilizzando la libreria parser. In Avro, i dati vengono sempre archiviati con lo schema corrispondente. Pertanto, possiamo sempre leggere uno schema senza generazione di codice.

Questo capitolo descrive come leggere lo schema by using parsers library e a serialize i dati utilizzando Avro.

Serializzazione utilizzando la libreria dei parser

Per serializzare i dati, dobbiamo leggere lo schema, creare i dati in base allo schema e serializzare lo schema utilizzando l'API Avro. La procedura seguente serializza i dati senza generare alcun codice:

Passo 1

Prima di tutto, leggi lo schema dal file. Per farlo, usaSchema.Parserclasse. Questa classe fornisce metodi per analizzare lo schema in diversi formati.

Istanziare il file Schema.Parser class passando il percorso del file in cui è archiviato lo schema.

Schema schema = new Schema.Parser().parse(new File("/path/to/emp.avsc"));

Passo 2

Crea l'oggetto di GenericRecord interfaccia, istanziando GenericData.Recordclasse come mostrato di seguito. Passa l'oggetto schema creato sopra al suo costruttore.

GenericRecord e1 = new GenericData.Record(schema);

Passaggio 3

Inserire i valori nello schema utilizzando il put() metodo del GenericData classe.

e1.put("name", "ramu");
e1.put("id", 001);
e1.put("salary",30000);
e1.put("age", 25);
e1.put("address", "chennai");

Passaggio 4

Crea un oggetto di DatumWriter interfaccia utilizzando il SpecificDatumWriterclasse. Converte gli oggetti Java in un formato serializzato in memoria. L'esempio seguente crea un'istanzaSpecificDatumWriter oggetto di classe per emp classe -

DatumWriter<emp> empDatumWriter = new SpecificDatumWriter<emp>(emp.class);

Passaggio 5

Istanziare DataFileWriter per empclasse. Questa classe scrive record serializzati di dati conformi a uno schema, insieme allo schema stesso, in un file. Questa classe richiede ilDatumWriter oggetto, come parametro per il costruttore.

DataFileWriter<emp> dataFileWriter = new DataFileWriter<emp>(empDatumWriter);

Passaggio 6

Apri un nuovo file per memorizzare i dati corrispondenti allo schema specificato utilizzando create()metodo. Questo metodo richiede lo schema e il percorso del file in cui devono essere memorizzati i dati, come parametri.

Nell'esempio riportato di seguito, lo schema viene passato utilizzando getSchema() metodo e il file di dati viene memorizzato nel percorso

/home/Hadoop/Avro/serialized_file/emp.avro.

empFileWriter.create(e1.getSchema(), new
File("/home/Hadoop/Avro/serialized_file/emp.avro"));

Passaggio 7

Aggiungi tutti i record creati al file utilizzando append( ) metodo come mostrato di seguito.

empFileWriter.append(e1);
empFileWriter.append(e2);
empFileWriter.append(e3);

Esempio: serializzazione mediante parser

Il seguente programma completo mostra come serializzare i dati utilizzando i parser:

import java.io.File;
import java.io.IOException;

import org.apache.avro.Schema;
import org.apache.avro.file.DataFileWriter;

import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericDatumWriter;
import org.apache.avro.generic.GenericRecord;

import org.apache.avro.io.DatumWriter;

public class Seriali {
   public static void main(String args[]) throws IOException{
	
      //Instantiating the Schema.Parser class.
      Schema schema = new Schema.Parser().parse(new File("/home/Hadoop/Avro/schema/emp.avsc"));
		
      //Instantiating the GenericRecord class.
      GenericRecord e1 = new GenericData.Record(schema);
		
      //Insert data according to schema
      e1.put("name", "ramu");
      e1.put("id", 001);
      e1.put("salary",30000);
      e1.put("age", 25);
      e1.put("address", "chenni");
		
      GenericRecord e2 = new GenericData.Record(schema);
		
      e2.put("name", "rahman");
      e2.put("id", 002);
      e2.put("salary", 35000);
      e2.put("age", 30);
      e2.put("address", "Delhi");
		
      DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<GenericRecord>(schema);
		
      DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<GenericRecord>(datumWriter);
      dataFileWriter.create(schema, new File("/home/Hadoop/Avro_work/without_code_gen/mydata.txt"));
		
      dataFileWriter.append(e1);
      dataFileWriter.append(e2);
      dataFileWriter.close();
		
      System.out.println(“data successfully serialized”);
   }
}

Sfoglia nella directory in cui è posizionato il codice generato. In questo caso, ahome/Hadoop/Avro_work/without_code_gen.

$ cd home/Hadoop/Avro_work/without_code_gen/

Ora copia e salva il programma sopra nel file denominato Serialize.java. Compilalo ed eseguilo come mostrato di seguito -

$ javac Serialize.java
$ java Serialize

Produzione

data successfully serialized

Se verifichi il percorso fornito nel programma, puoi trovare il file serializzato generato come mostrato di seguito.

Come accennato in precedenza, è possibile leggere uno schema Avro in un programma generando una classe corrispondente a uno schema o utilizzando la libreria parser. In Avro, i dati vengono sempre archiviati con lo schema corrispondente. Pertanto, possiamo sempre leggere un articolo serializzato senza generazione di codice.

Questo capitolo descrive come leggere lo schema using parsers library e Deserializing i dati utilizzando Avro.

Deserializzazione mediante libreria parser

I dati serializzati vengono archiviati nel file mydata.txt. Puoi deserializzarlo e leggerlo utilizzando Avro.

Seguire la procedura indicata di seguito per deserializzare i dati serializzati da un file.

Passo 1

Prima di tutto, leggi lo schema dal file. Per farlo, usaSchema.Parserclasse. Questa classe fornisce metodi per analizzare lo schema in diversi formati.

Istanziare il file Schema.Parser class passando il percorso del file in cui è archiviato lo schema.

Schema schema = new Schema.Parser().parse(new File("/path/to/emp.avsc"));

Passo 2

Crea un oggetto di DatumReader interfaccia utilizzando SpecificDatumReader classe.

DatumReader<emp>empDatumReader = new SpecificDatumReader<emp>(emp.class);

Passaggio 3

Istanziare DataFileReaderclasse. Questa classe legge i dati serializzati da un file. Richiede ilDatumReader oggetto e percorso del file in cui esistono i dati serializzati, come parametri per il costruttore.

DataFileReader<GenericRecord> dataFileReader = new DataFileReader<GenericRecord>(new File("/path/to/mydata.txt"), datumReader);

Passaggio 4

Stampare i dati deserializzati, utilizzando i metodi di DataFileReader.

  • Il hasNext() restituisce un valore booleano se sono presenti elementi nel lettore.

  • Il next() metodo di DataFileReader restituisce i dati nel lettore.

while(dataFileReader.hasNext()){

   em=dataFileReader.next(em);
   System.out.println(em);
}

Esempio: deserializzazione utilizzando la libreria dei parser

Il seguente programma completo mostra come deserializzare i dati serializzati utilizzando la libreria Parsers -

public class Deserialize {
   public static void main(String args[]) throws Exception{
	
      //Instantiating the Schema.Parser class.
      Schema schema = new Schema.Parser().parse(new File("/home/Hadoop/Avro/schema/emp.avsc"));
      DatumReader<GenericRecord> datumReader = new GenericDatumReader<GenericRecord>(schema);
      DataFileReader<GenericRecord> dataFileReader = new DataFileReader<GenericRecord>(new File("/home/Hadoop/Avro_Work/without_code_gen/mydata.txt"), datumReader);
      GenericRecord emp = null;
		
      while (dataFileReader.hasNext()) {
         emp = dataFileReader.next(emp);
         System.out.println(emp);
      }
      System.out.println("hello");
   }
}

Sfoglia nella directory in cui è posizionato il codice generato. In questo caso, è ahome/Hadoop/Avro_work/without_code_gen.

$ cd home/Hadoop/Avro_work/without_code_gen/

Ora copia e salva il programma sopra nel file denominato DeSerialize.java. Compilalo ed eseguilo come mostrato di seguito -

$ javac Deserialize.java
$ java Deserialize

Produzione

{"name": "ramu", "id": 1, "salary": 30000, "age": 25, "address": "chennai"}
{"name": "rahman", "id": 2, "salary": 35000, "age": 30, "address": "Delhi"}