¿Qué es Apache Avro?
Apache Avro es un framework de serialización de datos de código abierto desarrollado dentro del proyecto Apache Hadoop y publicado en 2009. A diferencia de Protocol Buffers (que requiere generación de código) o JSON (que carece de esquema), Avro adopta un enfoque distintivo: los esquemas se definen en JSON, se almacenan junto con los datos en el mismo archivo, y la codificación binaria está dirigida por esquemas en tiempo de ejecución — no se requiere generación de código estrictamente.
Avro es el formato de serialización principal para Apache Kafka (la plataforma dominante de streaming de eventos) y se usa ampliamente en el ecosistema Hadoop/Spark. Su combinación de codificación binaria compacta, esquema integrado y capacidades de evolución de esquema lo hace ideal para escenarios de streaming de eventos y pipelines de datos donde los formatos de datos evolucionan con el tiempo.
Cómo funciona Avro
Definición de esquema
Los esquemas Avro se escriben en JSON. Un esquema describe un tipo de dato — típicamente un record (como un struct u objeto):
{
"type": "record",
"name": "Usuario",
"namespace": "com.ejemplo",
"fields": [
{"name": "id", "type": "long"},
{"name": "nombre_usuario","type": "string"},
{"name": "email", "type": "string"},
{"name": "edad", "type": ["null", "int"], "default": null},
{"name": "creado_en", "type": {"type": "long", "logicalType": "timestamp-millis"}},
{"name": "etiquetas", "type": {"type": "array", "items": "string"}},
{"name": "direccion", "type": {
"type": "record",
"name": "Direccion",
"fields": [
{"name": "calle", "type": "string"},
{"name": "ciudad", "type": "string"},
{"name": "pais", "type": "string", "default": "ES"}
]
}}
]
}
Tipos de datos Avro
Tipos primitivos:
null,boolean,int,long,float,double,bytes,string
Tipos complejos:
record— campos nombrados (como struct/clase)enum— enumeración nombradaarray— lista ordenada de un tipomap— mapa con claves de cadena de un tipo de valorunion— valor de uno de varios tipos (comúnmente["null", "string"]para campos anulables)fixed— array de bytes de longitud fija
Tipos lógicos (anotaciones en tipos primitivos):
date— int, días desde la épocatimestamp-millis/timestamp-micros— long, marca de tiempo UTCdecimal— bytes o fixed con precisión+escala
Evolución de esquema: la característica diferencial
Como Protocol Buffers, Avro soporta la evolución segura del esquema, pero con un mecanismo diferente. Mientras que protobuf usa números de campo, Avro usa coincidencia de nombres con valores predeterminados.
Esquema del escritor vs esquema del lector
Al leer datos Avro, proporcionas tanto:
- Esquema del escritor: el esquema usado cuando se escribieron los datos
- Esquema del lector: el esquema que tu código espera leer
Las reglas de resolución de esquemas de Avro manejan las diferencias:
- Campo añadido con valor predeterminado: si el escritor no lo escribió, usar el predeterminado → compatible
- Campo eliminado: si el lector no lo necesita, omitirlo en los datos del escritor → compatible
- Promoción de tipo:
int→long,float→double→ compatible - Campo renombrado: usar el array
aliasesen el esquema del lector para coincidir con nombres antiguos
Avro con Apache Kafka y Schema Registry
En despliegues de Kafka, la gestión del esquema de Avro se maneja mediante Confluent Schema Registry — un servicio separado que almacena y versiona todos los esquemas:
# pip install fastavro confluent-kafka
import fastavro
import io
# Definir esquema
esquema = {
"type": "record",
"name": "Usuario",
"fields": [
{"name": "nombre", "type": "string"},
{"name": "email", "type": "string"},
{"name": "edad", "type": ["null", "int"], "default": None},
]
}
esquema_analizado = fastavro.parse_schema(esquema)
# Escribir Avro en archivo
registros = [
{"nombre": "Ana", "email": "ana@ejemplo.com", "edad": 30},
{"nombre": "Luis", "email": "luis@ejemplo.com", "edad": None},
]
with open('usuarios.avro', 'wb') as f:
fastavro.writer(f, esquema_analizado, registros, codec='snappy')
# Leer Avro desde archivo
with open('usuarios.avro', 'rb') as f:
lector = fastavro.reader(f)
esquema_escritor = lector.writer_schema # esquema integrado
for registro in lector:
print(registro) # {'nombre': 'Ana', 'email': '...', 'edad': 30}
Avro vs Protocol Buffers vs Parquet
| Característica | Avro | Protocol Buffers | Parquet |
|---|---|---|---|
| Orientación | Filas | Filas | Columnar |
| Esquema en el archivo | Sí (integrado) | No (externo .proto) | Sí (pie de archivo) |
| Generación de código | Opcional | Requerida | Opcional |
| Evolución de esquema | Basada en nombre + alias | Basada en número | Añadir/eliminar columnas |
| Compresión | A nivel de bloque | Ninguna (externa) | A nivel de columna |
| Uso principal | Kafka, streaming Hadoop | gRPC, microservicios | Analítica, data warehouse |
Cuándo usar Avro
Usa Avro cuando:
- Construyas pipelines de streaming de eventos basados en Kafka
- Trabajes con el ecosistema Hadoop/Spark (almacenamiento HDFS, tablas Hive)
- Necesites evolución de esquema con garantías de compatibilidad hacia adelante/atrás
- Java sea tu lenguaje principal (Avro tiene el mejor soporte Java)
- Las escrituras en streaming orientadas a filas sean el patrón de acceso principal
Usa Protocol Buffers en su lugar cuando:
- Construyas microservicios gRPC
- El tipado fuerte y la generación de código sean prioridades
Usa Parquet en su lugar cuando:
- El rendimiento de consultas analíticas sea la prioridad
- Los datos se leen principalmente, no se transmiten en streaming
Conversiones relacionadas
Conversiones frecuentes del catálogo: