Di Andrew Tan
La deriva dello schema e le modifiche a monte che rompono il sistema sono la causa principale dei fallimenti silenziosi dei dati — ma la maggior parte dei contenuti sui pipeline si concentra sull'infrastruttura, non sul comportamento del sistema sorgente
Correlato: Questo articolo copre il Modello 1 dalla nostra analisi di 50 postmortem di data pipeline da Uber, Netflix, Stripe e altri. La deriva dello schema ha rappresentato il 38% degli incidenti — la causa principale più comune che abbiamo riscontrato.
Il campo che ha cambiato tipo di martedì
Un team che conosco gestisce la riconciliazione dei pagamenti per un'azienda di e-commerce di medie dimensioni. Il loro pipeline estrae dati di transazione da un processore di pagamento di terze parti, li trasforma e li carica nel loro data warehouse. Funziona senza incidenti da due anni e mezzo.
Un martedì pomeriggio di novembre, il processore di pagamento ha aggiornato silenziosamente la loro API. Un campo — transaction_amount — è cambiato da una stringa (poiché alcuni sistemi legacy rappresentano il denaro come "47.50") a un float nativo (47.50). Nessuna versione. Nessun avviso di deprecazione. Nessuna email. La documentazione è stata aggiornata nel corso della settimana successiva.
Il pipeline non si è bloccato. Ha continuato a funzionare. Ha continuato a elaborare le transazioni. Ha continuato a segnalare successo.
Quello che ha smesso di fare è stato il casting corretto. La trasformazione a valle assumeva un input di stringa e applicava una regex per rimuovere i simboli di valuta prima di convertire. Con un float in arrivo, la regex non corrispondeva a nulla, la conversione produceva null, e ogni transazione per le sei ore successive aveva un importo di zero.
Sei ore di transazioni a zero dollari, tutte visualizzate come elaborate. Nessuno se ne è accorto fino a quando il rapporto di riconciliazione giornaliero è uscito la mattina successiva e i numeri sembravano come se un errore di arrotondamento avesse inghiottito l'azienda.
Racconto questa storia perché illustra qualcosa che la maggior parte degli scritti sull'architettura dei pipeline manca: i fallimenti più spaventosi non provengono dalla tua infrastruttura. Provengono da sistemi che non controlli.
Tre tipi di cambiamenti a monte
Non tutti i cambiamenti a monte sono uguali. Ho visto team bruciarsi con ciascuno di essi, e richiedono difese diverse.
I cambiamenti additivi sono quelli che i fornitori annunciano come "retrocompatibili". Nuovi campi appaiono nella risposta. I campi esistenti rimangono gli stessi. In teoria, il tuo pipeline dovrebbe essere a posto — non stai usando i nuovi campi. In pratica, i cambiamenti additivi rompono i pipeline quando colpiscono assunzioni implicite di dimensione (una risposta JSON ora supera un limite di buffer), quando le catture dello schema jolly iniziano a raccogliere campi che non ti aspettavi, o quando quel nuovo campo ha un nome che collide con un campo che hai già nella tua tabella di destinazione.
I cambiamenti che rompono sono almeno onesti. Il campo viene rinominato. Il tipo cambia. Un endpoint viene deprecato. Questi dovrebbero essere annunciati — e di solito lo sono, per fornitori rispettabili. Ma "annunciato" non significa "attuato". L'annuncio si trova in un digest email che nessuno legge perché il team che lo riceve non è il team che possiede il pipeline, e quando arriva la data di deprecazione, l'ingegnere originale si è trasferito in un'altra azienda.
I cambiamenti silenziosi sono la situazione del processore di pagamento. Il tipo di cui nessuno ti parla perché, dal punto di vista del fornitore, nulla è cambiato. La semantica è la stessa. I dati sono gli stessi. Solo il tipo è cambiato. O la codifica. O il comportamento di gestione dei null. I cambiamenti silenziosi sono quelli che si trasformano in eventi di corruzione dei dati di sei ore prima che qualcuno se ne accorga.
La proporzione di ciascun tipo varia in base alla maturità del fornitore. Le API finanziarie consolidate sono per lo più cambiamenti che rompono con lunghe finestre di deprecazione. I prodotti SaaS con cicli di rilascio rapidi sono per lo più silenziosi e additivi. I feed di dati forniti dai partner — il tipo non glamour, ma critico che gestisce le integrazioni B2B — sono genuinamente imprevedibili.

Perché la maggior parte dei pipeline fallisce al livello sbagliato
Ecco la questione sulla validazione dello schema: quasi tutti gli strumenti moderni per pipeline la supportano. Puoi definire schemi. Puoi validare all'ingestione. Puoi rifiutare record malformati.
La maggior parte dei team non lo fa, per ragioni comprensibili.
Nei primi giorni di un pipeline, lo schema cambia costantemente. Il sistema sorgente è ancora in sviluppo. Una validazione rigorosa fallirebbe il pipeline ogni volta che un campo viene aggiunto o rinominato durante l'iterazione normale. Quindi la validazione viene disattivata, o allentata a "miglior sforzo", e quando il pipeline raggiunge la produzione, nessuno si ricorda di stringerla di nuovo.
C'è anche una divisione filosofica su come i team pensano all'applicazione dello schema. La validazione rigorosa dello schema sembra difensiva. Sembra che tu stia costruendo un muro che romperà il pipeline ogni volta che il sistema sorgente respira. La gestione permissiva sembra pragmatica. Gestisci ciò che puoi, passa attraverso ciò che non puoi, lascia che la destinazione lo risolva.
Il problema con la gestione permissiva è che sposta la superficie di fallimento a valle e la rende invisibile. Il tuo pipeline non fallisce. La tua analisi o applicazione a valle elabora silenziosamente dati errati. E quando te ne accorgi — giorni dopo, quando un rapporto sembra sbagliato, o un utente segnala una discrepanza — i record corrotti sono stati mescolati con quelli legittimi, composti da trasformazioni a valle, e possibilmente agiti.
La validazione dello schema al livello del pipeline non riguarda l'essere rigorosi per il proprio bene. Riguarda il rendere i fallimenti rumorosi e precoci piuttosto che silenziosi e tardivi.
Le tre classi di difesa
Dopo aver osservato abbastanza di questi incidenti, ho scoperto che i team che gestiscono i cambiamenti a monte con grazia fanno tre cose costantemente.
Validazione della forma, non solo dei tipi. La validazione del tipo cattura la situazione del processore di pagamento. Ma la validazione della forma cattura i casi più sottili: un campo richiesto che diventa opzionale (e quindi a volte assente), un array che prima aveva sempre un elemento ora a volte ne ha zero, un oggetto che prima era piatto ora si annida un livello più in profondità.
La distinzione è importante perché gli errori di tipo producono fallimenti rumorosi. Le discrepanze di forma producono fallimenti silenziosi. Un campo presente il 99,9% delle volte e assente lo 0,1% delle volte produrrà un bug di gestione dei null che impiega settimane a emergere perché si attiva solo su tipi di transazione rari, o regioni geografiche specifiche, o metodi di pagamento di casi limite.
Monitoraggio della deriva dello schema, non solo dello stato del lavoro. Lo stato del lavoro ti dice se il pipeline è stato eseguito. Il monitoraggio della deriva dello schema ti dice se ciò che il pipeline ha elaborato oggi ha la stessa forma di ciò che ha elaborato ieri.
Questo non richiede una piattaforma di osservabilità sofisticata. La versione più semplice è un controllo giornaliero che calcola l'hash dello schema inferito di un campione di record da ciascuna fonte e avvisa se l'hash cambia. È grezzo ma efficace. La maggior parte degli eventi di deriva dello schema sono rilevabili con questo metodo entro 24 ore.
Versioni più sofisticate tracciano statistiche a livello di campo: tassi di null per campo, cardinalità per campo, distribuzione dei tipi per campo. Quando il tasso di null per transaction_amount passa dallo 0,0% allo 0,1%, qualcosa è cambiato a monte. Forse è intenzionale. Forse è un bug. In ogni caso, vuoi saperlo prima che diventi un problema.
Separare l'ingestione dall'elaborazione. Questo è il modello architettonico che compra più tempo quando i cambiamenti a monte accadono. Se il tuo pipeline ingerisce dati grezzi in una zona di atterraggio prima di elaborarli, hai l'opzione di riprodurre contro dati grezzi storici dopo aver risolto un problema di schema. Se l'ingestione e l'elaborazione sono accoppiate, perdi quell'opzione.
La zona di atterraggio grezza non deve essere costosa o complessa. Per molti casi d'uso, un archivio di oggetti solo append (S3, GCS, Azure Blob) con JSON grezzo partizionato è sufficiente. Il livello di trasformazione legge dalla zona di atterraggio, non direttamente dalla fonte. Quando qualcosa va storto a monte, correggi la trasformazione e riproduci. I dati sono ancora lì.

Test dei contratti al livello del pipeline: ne vale la pena?
Sentirai parlare dei test dei contratti guidati dal consumatore come la soluzione "corretta" a questo problema. L'idea è che il tuo pipeline pubblichi un contratto — questi sono i campi da cui dipendo, questi sono i tipi che mi aspetto, questo è ciò che considero un cambiamento che rompe — e il sistema sorgente è tenuto a validare contro quel contratto prima di distribuire cambiamenti.
Questo funziona bene quando controlli entrambi i lati dell'integrazione. Se stai integrando microservizi interni, o lavorando con un fornitore che prende sul serio la stabilità dell'integrazione, il test dei contratti è veramente prezioso. Strumenti come Pact lo rendono fattibile.
Per la maggior parte delle integrazioni che vedo in pratica — SaaS di terze parti, API dei partner, feed di dati da sistemi su cui non hai alcun potere — il test dei contratti è una bella teoria. Non puoi costringere un processore di pagamento a eseguire i tuoi test Pact prima di distribuire. Non puoi negoziare diritti di pubblicazione del contratto con un fornitore il cui team legale non ha mai sentito parlare di contratti guidati dal consumatore.
Il quadro più pratico è: cosa puoi fare dalla tua parte del confine per rilevare i cambiamenti e recuperare rapidamente da essi?
Il che mi riporta al monitoraggio dello schema, alle zone di atterraggio e alla validazione a livello di pipeline. Non glamour. Non la soluzione tecnicamente interessante. Ma quella che funziona effettivamente su tutta la gamma di scenari a monte che incontrerai.
La domanda da porre a ogni avvio di integrazione
Ho iniziato a porre una domanda a ogni revisione del design dell'integrazione: Qual è il processo quando questo cambia senza preavviso?
Non se. Quando.
Sembra pessimista. Il team di integrazione dei partner a volte lo prende sul personale. Ma la domanda forza una conversazione che quasi sempre porta alla luce assunzioni che nessuno aveva reso esplicite: l'assunzione che il team del sistema sorgente comunicherà i cambiamenti che rompono, l'assunzione che qualcuno nel team di integrazione leggerà il changelog, l'assunzione che il pipeline può tollerare X giorni di dati errati prima che qualcuno se ne accorga.
Quelle assunzioni sono di solito sbagliate. Renderle esplicite ti dà la possibilità di progettare intorno a esse.
La risposta a "cosa succede quando questo cambia senza preavviso" dovrebbe coinvolgere almeno: dove si attiva l'allerta, chi la riceve, quanto rapidamente il team può identificare quale campo è cambiato, e quanto rapidamente possono riprodurre i dati interessati dalla zona di atterraggio grezza. Se la risposta è "dovremmo indagare e probabilmente chiamare il fornitore", il pipeline non è pronto per la produzione.
Dove si inserisce layline.io in questo
L'evoluzione dello schema è una delle cose a cui pensiamo molto in come layline.io gestisce l'elaborazione dei dati. Quando ti occupi di pipeline sia batch che streaming — e la realtà è che la maggior parte dei team gestisce entrambi indefinitamente — il problema del cambiamento a monte si complica. Un cambiamento di schema in una fonte streaming ti colpisce in tempo reale. Lo stesso cambiamento in una fonte batch potrebbe non emergere per 24 ore.
Il modello di elaborazione di layline.io ti supporta con l'evoluzione dello schema attraverso il routing esplicito delle versioni: quando viene introdotta una nuova versione dello schema, puoi applicare logiche e validazioni separate o indirizzare quei record a un flusso separato per la validazione e la gestione complessiva, piuttosto che lasciarli contaminare il tuo percorso di elaborazione principale.
Non è magia. Devi ancora progettare la tua integrazione con l'assunzione che le cose a monte cambieranno. Ma significa che quando cambiano, la superficie di fallimento è più piccola e il percorso di recupero è più veloce.
I team che gestiscono i cambiamenti a monte con grazia non sono quelli con l'infrastruttura più sofisticata. Sono quelli che hanno smesso di presumere che il sistema sorgente non li sorprenderà mai.
Se il tuo team sta affrontando la deriva dello schema o l'affidabilità delle integrazioni a monte, il motore di elaborazione di layline.io gestisce l'evoluzione dello schema e la resilienza del pipeline per carichi di lavoro sia batch che in tempo reale. La Community Edition è gratuita da esplorare.
Andrew Tan è un imprenditore seriale e fondatore di layline.io, costruendo infrastrutture di elaborazione dati aziendali che gestiscono carichi di lavoro sia batch che in tempo reale su larga scala.



