Un'implementazione open source di WAP che utilizza Apache Iceberg, Lambdas e Project Nessie, tutti eseguiti interamente in Python
In questo post del blog forniamo un'implementazione di riferimento pratica per i modelli Write-Audit-Publish (WAP) su un data Lake, utilizzando Apache Iceberg come formato di tabella aperta e Progetto Nessie come catalogo di dati che supporta la semantica simile a git.
Abbiamo scelto Nessie perché le sue capacità di ramificazione forniscono una buona astrazione per implementare un progetto WAP. Ancora più importante, abbiamo scelto di continuare a costruire PyIceberg per eliminare la necessità della JVM in termini di esperienza degli sviluppatori. Per eseguire l'intero progetto, comprese le applicazioni integrate, infatti, avremo bisogno solo di Python e AWS.
Mentre Nessie è tecnicamente costruito in Java, il catalogo dati viene eseguito come un contenitore da AWS Lightsail in questo progetto interagiremo con esso solo attraverso il suo endpoint. Di conseguenza, possiamo esprimere l'intera logica WAP, comprese le query a valle, solo in Python!
Perché PyIceberg è abbastanza nuovo, un sacco di cose in realtà non sono supportate immediatamente. In particolare, la scrittura è ancora agli inizi e la ramificazione delle tabelle Iceberg non è ancora supportata. Quindi quello che troverai qui è il risultato di un lavoro originale che abbiamo fatto noi stessi per creare tabelle Iceberg ramificate Nessie possibile direttamente da Python.
Quindi è successo tutto questo, più o meno.
Nel 2017, Michelle Winters di Netflix parlato su un modello di progettazione chiamato Write-Audit-Publish (WAP) nei dati. Essenzialmente, il WAP è un design funzionale volto a rendere i controlli sulla qualità dei dati facili da implementare Prima i dati diventano disponibili per i consumatori a valle.
Ad esempio, un caso d’uso atipico è la qualità dei dati al momento dell’acquisizione. Il flusso sembrerà creare un ambiente di staging ed eseguire test di qualità sui dati appena acquisiti, prima di renderli disponibili a qualsiasi applicazione downstream.
Come tradisce il nome, le fasi sono essenzialmente tre:
- Scrivere. Collocare i dati in un luogo non accessibile ai consumatori a valle (ad esempio un ambiente di staging o una filiale).
- Controllo. Trasformare e testare i dati per assicurarsi che soddisfino le specifiche (ad esempio, verificare se lo schema è cambiato improvvisamente o se sono presenti valori imprevisti, come NULL).
- Pubblicare. Mettere i dati nel luogo in cui i consumatori possano leggerli (ad esempio il data lake di produzione).
Questo è solo un esempio delle possibili applicazioni dei modelli WAP. È facile vedere come può essere applicato in diverse fasi del ciclo di vita dei dati, dall'ETL e l'acquisizione dei dati, alle complesse pipeline di dati che supportano analisi e applicazioni ML.
Nonostante sia così utile, Il WAP non è ancora molto diffusoe solo di recente le aziende hanno iniziato a pensarci in modo più sistematico. L'ascesa di formati di tavoli aperti e progetti come Nessie E LagoFS sta accelerando il processo, ma è ancora un po' avanguardia.
In ogni caso, è un ottimo modo di pensare ai dati ed è estremamente utile per risolvere alcuni dei problemi più diffusi che tengono svegli gli ingegneri la notte. Vediamo quindi come possiamo implementarlo.
Non avremo una discussione teorica sul WAP né forniremo un'indagine esaustiva dei diversi modi per implementarlo (Alex Merced da Drammatico E Einat Orr da LagoFs stanno già facendo un lavoro fenomenale in questo). Forniremo invece un'implementazione di riferimento per WAP su un data Lake.
👉 Quindi allacciati le cinture, clona il Repoe fai un giro!
📌Fo maggiori dettagli, fare riferimento a LEGGIMI del progetto.
L'idea qui è quella di simulare un flusso di lavoro di inserimento e implementare un modello WAP ramificando il data Lake ed eseguendo un test sulla qualità dei dati prima di decidere se inserire i dati nella tabella finale del data Lake.
Utilizziamo le funzionalità di ramificazione di Nessie per ottenere il nostro ambiente sandbox in cui i dati non possono essere letti dai consumatori a valle e AWS Lambda per eseguire la logica WAP.
In sostanza, ogni volta che viene caricato un nuovo file parquet, una Lambda si attiverà, creerà un ramo nel catalogo dati e aggiungerà i dati in una tabella Iceberg. Quindi, viene eseguito un semplice test sulla qualità dei dati con PyIceberg per verificare se una determinata colonna nella tabella contiene alcuni valori NULL.
Se la risposta è sì, il test della qualità dei dati fallisce. Il nuovo ramo non verrà unito al ramo principale del catalogo dati, rendendo impossibile la lettura dei dati nel ramo principale di Data Lake. Verrà invece inviato un messaggio di avviso a Lento.
Se la risposta è no, e i dati non contengono NULL, il test di qualità dei dati è stato superato. La nuova filiale verrà così confluita nella principale ramo del catalogo dati e i dati verranno aggiunti nella tabella Iceberg nel data Lake affinché altri processi possano leggerli.
Tutti i dati sono completamente sintetici e vengono generati automaticamente semplicemente eseguendo il progetto. Naturalmente diamo la possibilità di scegliere se generare dati conformi alle specifiche di qualità dei dati o generare dati che includano alcuni valori NULL.
Per implementare l'intero flusso end-to-end, utilizzeremo i seguenti componenti:
Questo progetto è piuttosto autonomo e viene fornito con script per configurare l'intera infrastruttura, quindi richiede solo familiarità a livello introduttivo con AWS e Python.
Inoltre, non vuole essere una soluzione pronta per la produzione, ma piuttosto un'implementazione di riferimento, un punto di partenza per scenari più complessi: il codice è dettagliato e fortemente commentato, rendendo facile modificare ed estendere i concetti di base per adattarsi meglio ai casi d'uso di chiunque .
Per visualizzare i risultati del test sulla qualità dei dati, forniamo un file molto semplice Illuminato app che può essere utilizzata per vedere cosa succede quando alcuni nuovi dati vengono caricati nella prima posizione su S3, quella che non è disponibile per i consumatori a valle.
Possiamo utilizzare l'app per verificare quante righe sono presenti nella tabella nei diversi rami e per i rami diversi da principaleè facile vedere in quale colonna il test della qualità dei dati ha fallito e in quante righe.
Una volta che avremo un flusso WAP basato su Iceberg, potremo sfruttarlo per implementare un design componibile per i nostri consumatori a valle. Nel nostro repository forniamo istruzioni per a Fiocco di neve integrazione come un modo per esplorare questa possibilità architettonica.
Questo è uno dei principi principali del Casa sul lago architettura, concepita per essere più flessibile dei moderni data warehouse e più fruibile dei tradizionali data lake.
Da un lato, Lakehouse punta sullo sfruttamento dell'archivio oggetti per eliminare la ridondanza dei dati e allo stesso tempo ridurre i costi di archiviazione. Dall’altro, dovrebbe fornire maggiore flessibilità nella scelta di diversi motori di calcolo per scopi diversi.
Tutto ciò sembra molto interessante in teoria, ma sembra anche molto complicato da progettare su larga scala. Anche una semplice integrazione tra Snowflake e un bucket S3 come volume esterno è francamente piuttosto noiosa.
E in effetti, non lo sottolineeremo mai abbastanza, il passaggio a un'architettura Lakehouse completa richiede molto lavoro. Mi piace molto!
Detto questo, anche un viaggio di mille miglia inizia con un solo passo, quindi perché non iniziare cogliendo i frutti più bassi con conseguenze pratiche semplici ma molto tangibili?
L'esempio nel repository mostra uno di questi semplici casi d'uso: test WAP e qualità dei dati. Il modello WAP qui offre la possibilità di spostare il calcolo richiesto per i test sulla qualità dei dati (e possibilmente per alcuni ETL di acquisizione) fuori dal data warehouse, pur mantenendo la possibilità di sfruttare Snowflake per carichi di lavoro analitici di valore più elevato su artefatti certificati. Ci auguriamo che questo post possa aiutare gli sviluppatori a creare le proprie prove di concetto e a utilizzare il file
L'implementazione di riferimento qui proposta presenta diversi vantaggi:
Le tabelle sono migliori dei file
È storicamente difficile contrastare i data lake, poiché le astrazioni dei dati sono molto diverse da quelle tipicamente adottate nei buoni vecchi database. Framework di Big Data come Scintilla inizialmente ha fornito la capacità di elaborare grandi quantità di dati grezzi archiviati come file in diversi formati (ad esempio parquet, csv, ecc.), ma le persone spesso non pensano in termini di file: pensano in termini di tabelle.
Per questo motivo utilizziamo un formato di tabella aperta. Iceberg trasforma l'astrazione principale del data Lake in tabelle anziché in file, il che rende le cose notevolmente più intuitive. Ora possiamo utilizzare i motori di query SQL in modo nativo per esplorare i dati e possiamo contare su Iceberg per fornire la corretta evoluzione dello schema.
L'interoperabilità fa bene
Iceberg consente inoltre una maggiore interoperabilità dal punto di vista architetturale. Uno dei principali vantaggi derivanti dall'utilizzo dei formati di tabella aperti è che i dati possono essere conservati nell'archivio oggetti mentre i motori SQL ad alte prestazioni (Spark, Trino, Drammatico) e Magazzini (Fiocco di neve, Spostamento verso il rosso) può essere utilizzato per interrogarlo. Il fatto che Iceberg sia supportato dalla maggior parte dei motori computazionali disponibili ha profonde conseguenze sul modo in cui possiamo progettare la nostra piattaforma dati.
Come descritto sopra, l'integrazione suggerita con Snowflake ha lo scopo di dimostrare che è possibile spostare deliberatamente il calcolo necessario per l'ETL di acquisizione e i test di qualità dei dati al di fuori del Warehouse e mantenere quest'ultimo per lavori di analisi su larga scala e interrogazioni dell'ultimo miglio richiedono prestazioni elevate. Su larga scala, questa idea può tradursi in costi notevolmente inferiori.
I rami sono astrazioni utili
Il modello WAP richiede un modo per scrivere i dati in una posizione in cui i consumatori non possano leggerli accidentalmente. La semantica di ramificazione fornisce naturalmente un modo per implementare tutto ciò, motivo per cui utilizziamo Nessie per sfruttare la semantica di ramificazione a livello di catalogo dati. Nessie si basa su Iceberg e sulle sue funzionalità di viaggio nel tempo e di ramificazione delle tabelle. Gran parte del lavoro svolto nel nostro repository è quello di far funzionare Nessie direttamente con Python. Il risultato è che è possibile interagire con il catalogo Nessie e scrivere tabelle Iceberg in diversi rami del catalogo dati senza un processo basato su JVM da scrivere.
Esperienza per sviluppatori più semplice
Infine, rendere l'esperienza end-to-end completamente basata su Python semplifica notevolmente la configurazione del sistema e l'interazione con esso. Qualsiasi altro sistema di cui siamo a conoscenza richiederebbe una JVM o un servizio ospitato aggiuntivo per riscrivere le tabelle Iceberg in rami diversi, mentre in questa implementazione l'intera logica WAP può essere eseguita all'interno di un'unica funzione lambda.
Non c'è nulla di intrinsecamente sbagliato nella JVM. È un componente fondamentale di molti framework Big Data, poiché fornisce un'API comune per lavorare con risorse specifiche della piattaforma, garantendo al tempo stesso sicurezza e correttezza. Tuttavia, la JVM ha un impatto negativo dal punto di vista dell'esperienza dello sviluppatore. Chiunque abbia lavorato con Spark sa che i sistemi basati su JVM tendono ad essere pignoli e falliscono con errori misteriosi. Per molte persone che lavorano con i dati e considerano Python come loro lingua franca il vantaggio della JVM viene pagato con la moneta dell'usabilità.
Ci auguriamo che sempre più persone siano entusiaste dei progetti componibili come noi, speriamo che standard aperti come Iceberg e Arrow diventino la norma, ma soprattutto speriamo che questo sia utile.
Così è andata.
Fonte: towardsdatascience.com