Una implementación de código abierto de WAP que utiliza Apache Iceberg, Lambdas y Project Nessie, todos ejecutando completamente Python
En esta publicación de blog, proporcionamos una implementación de referencia sensata para patrones de escritura, auditoría y publicación (WAP) en un lago de datos, utilizando Iceberg apache como formato de tabla abierta, y Proyecto Nessie como un catálogo de datos que soporta una semántica similar a git.
Nosotros elegimos nessie porque sus capacidades de ramificación proporcionan una buena abstracción para implementar un diseño WAP. Lo más importante es que elegimos aprovechar PyIceberg para eliminar la necesidad de la JVM en términos de experiencia del desarrollador. De hecho, para ejecutar todo el proyecto, incluidas las aplicaciones integradas, sólo necesitaremos Python y AWS.
Mientras nessie está técnicamente construido en Java, el catálogo de datos se ejecuta como un contenedor por Vela de luz de AWS En este proyecto, vamos a interactuar con él solo a través de su punto final. En consecuencia, podemos expresar toda la lógica WAP, incluidas las consultas posteriores, ¡solo en Python!
Porque PyIceberg es bastante nuevo, muchas cosas en realidad no son compatibles desde el primer momento. En particular, la escritura aún está en sus inicios y aún no se admite la bifurcación de tablas Iceberg. Entonces, lo que encontrará aquí es el resultado de un trabajo original que hicimos nosotros mismos para crear mesas Iceberg ramificadas en nessie posible directamente desde Python.
Entonces todo esto pasó, más o menos.
En 2017, Michelle Winters de Netflix habló sobre un patrón de diseño llamado Write-Audit-Publish (WAP) en datos. Básicamente, WAP es un diseño funcional destinado a facilitar la implementación de controles de calidad de datos. antes los datos estén disponibles para los consumidores intermedios.
Por ejemplo, un caso de uso atípico es la calidad de los datos en el momento de la ingesta. El flujo parecerá crear un entorno de prueba y ejecutar pruebas de calidad en datos recién ingeridos, antes de ponerlos a disposición de cualquier aplicación posterior.
Como su nombre lo indica, existen esencialmente tres fases:
- Escribir. Coloque los datos en una ubicación que no sea accesible para los consumidores posteriores (por ejemplo, un entorno de prueba o una sucursal).
- Auditoría. Transforme y pruebe los datos para asegurarse de que cumplan con las especificaciones (por ejemplo, verifique si el esquema cambió abruptamente o si hay valores inesperados, como NULL).
- Publicar. Coloque los datos en un lugar donde los consumidores puedan leerlos (por ejemplo, el lago de datos de producción).
Este es sólo un ejemplo de las posibles aplicaciones de los patrones WAP. Es fácil ver cómo se puede aplicar en diferentes etapas del ciclo de vida de los datos, desde ETL y la ingestión de datos, hasta canales de datos complejos que respaldan aplicaciones de análisis y aprendizaje automático.
A pesar de ser tan útil, WAP todavía no está muy extendido, y sólo recientemente las empresas han empezado a pensar en ello de forma más sistemática. El auge de formatos de mesa abierta y proyectos como nessie y LagoFS está acelerando el proceso, pero todavía un poco vanguardia.
En cualquier caso, es una muy buena manera de pensar en los datos y es extremadamente útil para solucionar algunos de los problemas más extendidos que mantienen despiertos a los ingenieros. Así que veamos cómo podemos implementarlo.
No vamos a tener una discusión teórica sobre WAP ni proporcionaremos un estudio exhaustivo de las diferentes formas de implementarlo (Alex Merced de Dremio y Einat Orr de lagofs ya están haciendo un trabajo fenomenal en eso). En su lugar, proporcionaremos una implementación de referencia para WAP en un lago de datos.
👉 Así que abróchate el cinturón, clona el repositorio¡Y dale una vuelta!
📌Fo más detalles, consulte la LÉAME del proyecto.
La idea aquí es simular un flujo de trabajo de ingesta e implementar un patrón WAP ramificando el lago de datos y ejecutando una prueba de calidad de los datos antes de decidir si colocar los datos en la tabla final del lago de datos.
Usamos las capacidades de ramificación de Nessie para lograr nuestro entorno de espacio aislado donde los consumidores intermedios no pueden leer los datos y AWS Lambda para ejecutar la lógica WAP.
Básicamente, cada vez que se carga un nuevo archivo de parquet, se activará un Lambda, creará una rama en el catálogo de datos y agregará los datos a una tabla Iceberg. Luego, se realiza una prueba simple de calidad de datos con PyIceberg para verificar si una determinada columna de la tabla contiene algunos valores NULL.
Si la respuesta es sí, la prueba de calidad de los datos falla. La nueva rama no se fusionará con la rama principal del catálogo de datos, lo que hará que sea imposible leer los datos en la rama principal del lago de datos. En su lugar, se enviará un mensaje de alerta a Flojo.
Si la respuesta es no, y los datos no contienen ningún NULL, se pasa la prueba de calidad de los datos. De este modo, la nueva sucursal se fusionará con la principal rama del catálogo de datos y los datos se agregarán a la tabla Iceberg en el lago de datos para que otros procesos los lean.
Todos los datos son completamente sintéticos y se generan automáticamente con solo ejecutar el proyecto. Por supuesto, brindamos la posibilidad de elegir si generar datos que cumplan con las especificaciones de calidad de datos o generar datos que incluyan algunos valores NULL.
Para implementar todo el flujo de un extremo a otro, utilizaremos los siguientes componentes:
Este proyecto es bastante autónomo y viene con scripts para configurar toda la infraestructura, por lo que solo requiere un nivel introductorio de familiaridad con AWS y Python.
Tampoco pretende ser una solución lista para producción, sino más bien una implementación de referencia, un punto de partida para escenarios más complejos: el código es detallado y está muy comentado, lo que facilita la modificación y ampliación de los conceptos básicos para adaptarse mejor a los casos de uso de cualquier persona. .
Para visualizar los resultados de la prueba de calidad de los datos, proporcionamos una muy simple iluminado aplicación que se puede utilizar para ver qué sucede cuando se cargan algunos datos nuevos en la primera ubicación en S3, la que no está disponible para los consumidores intermedios.
Podemos usar la aplicación para verificar cuántas filas hay en la tabla en las diferentes ramas y para las ramas distintas a principales fácil ver en qué columna falló la prueba de calidad de los datos y en cuántas filas.
Una vez que tengamos un flujo WAP basado en Iceberg, podremos aprovecharlo para implementar un diseño componible para nuestros consumidores intermedios. En nuestro repositorio proporcionamos instrucciones para un Copo de nieve la integración como forma de explorar esta posibilidad arquitectónica.
Éste es uno de los principios principales de la Casa del Lago arquitectura, concebida para ser más flexible que los almacenes de datos modernos y más utilizable que los lagos de datos tradicionales.
Por un lado, Lakehouse depende de aprovechar el almacenamiento de objetos para eliminar la redundancia de datos y al mismo tiempo reducir el costo de almacenamiento. Por otro lado, se supone que proporciona más flexibilidad a la hora de elegir diferentes motores informáticos para diferentes propósitos.
Todo esto suena muy interesante en teoría, pero también parece muy complicado de diseñar a escala. Incluso una simple integración entre Snowflake y un depósito S3 como volumen externo es francamente bastante tediosa.
Y, de hecho, no podemos enfatizar esto lo suficiente: pasar a una arquitectura Lakehouse completa requiere mucho trabajo. ¡Me gusta mucho!
Dicho esto, incluso un viaje de mil millas comienza con un solo paso, así que ¿por qué no empezamos por alcanzar los frutos más bajos con consecuencias prácticas simples pero muy tangibles?
El ejemplo del repositorio muestra uno de estos casos de uso simples: WAP y pruebas de calidad de datos. El patrón WAP aquí es una oportunidad para mover el cálculo requerido para las pruebas de calidad de los datos (y posiblemente para alguna ingesta ETL) fuera del almacén de datos, sin dejar de mantener la posibilidad de aprovechar Snowflake para cargas de trabajo de análisis de mayor valor en artefactos certificados. Esperamos que esta publicación pueda ayudar a los desarrolladores a crear su propia prueba de conceptos y utilizar el
La implementación de referencia aquí propuesta tiene varias ventajas:
Las tablas son mejores que los archivos.
Históricamente, es difícil desarrollar lagos de datos, ya que las abstracciones de datos son muy diferentes de las que normalmente se adoptan en las bases de datos antiguas. Marcos de Big Data como Chispa – chispear Primero proporcionó la capacidad de procesar grandes cantidades de datos sin procesar almacenados como archivos en diferentes formatos (por ejemplo, parquet, csv, etc.), pero la gente a menudo no piensa en términos de archivos: lo piensa en términos de tablas.
Por este motivo utilizamos un formato de tabla abierta. Iceberg convierte la abstracción del lago de datos principal en tablas en lugar de archivos, lo que hace que las cosas sean considerablemente más intuitivas. Ahora podemos usar motores de consultas SQL de forma nativa para explorar los datos y podemos contar con Iceberg para que se encargue de proporcionar la evolución correcta del esquema.
La interoperabilidad es buena para ti
Iceberg también permite una mayor interoperabilidad desde el punto de vista arquitectónico. Uno de los principales beneficios de utilizar formatos de tabla abiertos es que los datos se pueden mantener en el almacén de objetos mientras los motores SQL de alto rendimiento (Spark, trino, Dremio) y Almacenes (Copo de nieve, corrimiento al rojo) se puede utilizar para consultarlo. El hecho de que Iceberg sea compatible con la mayoría de los motores computacionales que existen tiene profundas consecuencias en la forma en que podemos diseñar nuestra plataforma de datos.
Como se describió anteriormente, nuestra integración sugerida con Snowflake tiene como objetivo mostrar que se puede mover deliberadamente el cálculo necesario para la ingestión ETL y las pruebas de calidad de datos fuera del almacén, y mantener este último para trabajos de análisis a gran escala y consultas de última milla. requieren un alto rendimiento. A escala, esta idea puede traducirse en costos significativamente más bajos.
Las ramas son abstracciones útiles
El patrón WAP requiere una forma de escribir datos en una ubicación donde los consumidores no puedan leerlos accidentalmente. La semántica de bifurcación proporciona naturalmente una forma de implementar esto, razón por la cual utilizamos Nessie para aprovechar la semántica de bifurcación a nivel del catálogo de datos. Nessie se basa en Iceberg y en sus funcionalidades de viaje en el tiempo y ramificación de tablas. Gran parte del trabajo realizado en nuestro repositorio es hacer que Nessie funcione directamente con Python. El resultado es que se puede interactuar con el catálogo de Nessie y escribir tablas Iceberg en diferentes ramas del catálogo de datos sin necesidad de escribir un proceso basado en JVM.
Experiencia de desarrollador más sencilla
Finalmente, hacer que la experiencia de un extremo a otro esté completamente basada en Python simplifica notablemente la configuración del sistema y la interacción con él. Cualquier otro sistema que conozcamos requeriría una JVM o un servicio alojado adicional para volver a escribir en tablas Iceberg en diferentes ramas, mientras que en esta implementación toda la lógica WAP puede ejecutarse dentro de una única función lambda.
No hay nada inherentemente malo en la JVM. Es un componente fundamental de muchos marcos de Big Data, ya que proporciona una API común para trabajar con recursos específicos de la plataforma, al tiempo que garantiza la seguridad y la corrección. Sin embargo, la JVM pasa factura desde la perspectiva de la experiencia del desarrollador. Cualquiera que haya trabajado con Spark sabe que los sistemas basados en JVM tienden a ser quisquillosos y fallar con errores misteriosos. Para muchas personas que trabajan con datos y consideran Python como su lingua franca La ventaja de la JVM se paga con la moneda de la usabilidad.
Esperamos que más personas estén entusiasmadas con los diseños componibles como nosotros, esperamos que los estándares abiertos como Iceberg y Arrow se conviertan en la norma, pero sobre todo esperamos que esto sea útil.
Así que va.