
Introduzione allo streaming con Kafka
Fondamenti di Apache Kafka: architettura, concetti chiave e pattern di utilizzo per analytics.
Cosa imparerai
- Comprendere il problema analitico e il contesto decisionale
- Applicare esempi, metriche e controlli a casi reali
Collegamenti
import pandas as pd
Introduzione allo streaming con Kafka
Un sistema digitale non aspetta la chiusura del giorno per reagire. Ordini, click, pagamenti e log arrivano mentre il business sta già prendendo decisioni, e la domanda diventa come trasportarli da una parte all’altra senza costruire un’integrazione fragile per ogni coppia di sistemi. Kafka propone una risposta precisa: trattare gli eventi come un log condiviso, ordinato per chiave e riutilizzabile, invece di replicare connessioni punto a punto che si rompono appena cambia qualcosa. Questa lezione parte da quel cambio di modello e mostra perché conta.
Perché lo streaming cambia il problema
Quando i dati si muovono in batch notturni, l’azienda lavora sempre con una fotografia vecchia di ore. Lo streaming non serve solo a fare le stesse cose più in fretta: cambia quali decisioni diventano possibili. Un sistema antifrode che vede la transazione mentre avviene può bloccarla; lo stesso sistema che la vede il giorno dopo può solo scrivere un report.
Conviene leggere Kafka tenendo distinti tre piani. C’è l’evento, cioè il fatto che è accaduto qualcosa. C’è l’infrastruttura che lo trasporta e lo conserva. E c’è la decisione che quei dati dovrebbero migliorare. Kafka è utile quando riduce l’accoppiamento tra sistemi, rende i dati riusabili e conserva abbastanza storia da poter correggere un errore a posteriori. Diventa costoso quando viene scelto solo perché “real time” suona meglio di “batch”, senza che nessuno abbia bisogno della latenza che promette.
I concetti fondamentali
Un topic è un flusso logico di messaggi, paragonabile a una tabella in un database: user-events, orders, page-views. Un’azienda può averne centinaia.
Ogni topic è diviso in partizioni per scalare orizzontalmente. Ogni partizione è un log immutabile e ordinato. I messaggi nella stessa partizione mantengono l’ordine, ma l’ordine globale tra partizioni diverse non è garantito: è una delle prime cose che chi arriva da un database sottovaluta.
L’offset è la posizione di un messaggio dentro la partizione, un numero intero crescente. I consumer tengono traccia dell’offset per sapere fin dove hanno già letto. Il producer scrive su Kafka e decide in quale partizione finisce ogni messaggio, di default tramite l’hash della chiave. Il consumer legge da Kafka e appartiene a un consumer group: ogni partizione viene assegnata a un solo consumer del gruppo, e questo garantisce che ogni messaggio sia processato una volta per gruppo. Il broker è un singolo server Kafka, e un cluster ne tiene più di uno per tolleranza ai guasti e throughput.
Il log immutabile
Qui sta la differenza vera rispetto a una coda di messaggi tradizionale come RabbitMQ, dove un messaggio sparisce appena viene consumato. Kafka invece conserva i messaggi per un periodo configurabile, di default sette giorni ma potenzialmente all’infinito. Questo trasforma Kafka da semplice sistema di messaggistica in un event store vero e proprio.
Le conseguenze pratiche sono concrete. Puoi rileggere i messaggi dall’inizio e riprocessare lo storico quando scopri un bug nella logica a valle. Più consumer group possono leggere gli stessi dati in modo indipendente, senza interferire tra loro. E un nuovo consumer che si aggiunge in seguito può ripartire da zero e recuperare tutta la storia. È il pattern dell’event sourcing: il log di Kafka è la fonte di verità, e ogni sistema a valle deriva il proprio stato leggendolo.
Quando Kafka serve e quando no
Kafka ha senso per flussi di eventi ad alto throughput, indicativamente sopra i 10.000 messaggi al secondo, per microservizi che vuoi tenere disaccoppiati, per event sourcing, change data capture e analytics in tempo reale. Sotto questa soglia il rapporto tra valore e complessità operativa cambia segno.
Kafka non serve, invece, per code di task semplici, dove RabbitMQ o SQS bastano e costano meno; per volumi bassi, sotto il centinaio di messaggi al secondo, dove l’overhead di gestione non si ripaga; e per applicazioni che richiedono transazioni ACID, dove un database resta la scelta giusta. Scegliere Kafka per inerzia, perché lo usano tutti, è uno dei modi più comuni di pagare disciplina operativa senza riceverne i benefici.
Come impostare la scelta
La domanda da fare prima di introdurre uno streaming backbone non è “quale metrica calcolo” ma “quale decisione dovrà migliorare grazie a questo”. Un’integrazione, una dashboard o un consumer group hanno valore solo se riducono l’incertezza di una scelta concreta. Se non cambiano nessuna decisione, sono documentazione o teatro tecnico.
Un modo ordinato di lavorare segue questa sequenza:
- definire il problema in linguaggio di business;
- identificare l’unità di analisi corretta, che sia utente, account, evento, sessione, ordine o campagna;
- controllare se i dati misurano davvero il fenomeno o solo una sua ombra;
- costruire una metrica interpretabile;
- segmentare, perché una media globale può nascondere due gruppi che si muovono in direzioni opposte;
- trasformare il risultato in una raccomandazione verificabile.
Conviene anche dichiarare in modo esplicito l’unità di lavoro (topic, evento, schema, producer, consumer o stream processor), il segnale principale che osservi (latenza, throughput, lag, compatibilità schema, perdita dati), la baseline rispetto a cui leggi il risultato e la decisione attesa, che sia un contratto evento, una pipeline o una policy operativa. Il rischio costante è scambiare un numero disponibile per una prova sufficiente.
Un caso di scelta
Un team deve decidere se sostituire export schedulati e webhook fragili con un backbone a eventi. Prima di portare dentro Kafka conviene valutare il volume reale, il fan out verso i consumer, la necessità di replay, l’ordine per chiave e le competenze operative disponibili. Uno streaming system risolve integrazioni complesse, ma in cambio chiede disciplina nuova: chi possiede i topic, come si gestiscono gli schemi, come si misura il lag.
La logica con cui si legge un risultato resta la stessa anche fuori da Kafka. Se un numero migliora, potrebbe essere un effetto reale oppure una normale oscillazione, e la mossa prudente è cercare un confronto e un segmento. Se un solo segmento si muove più degli altri, la media aggregata sta nascondendo una differenza, quindi conviene separare le coorti. Se il costo cresce insieme al risultato, l’impatto va letto sul margine e non in valore assoluto.
Esempio SQL: una vista di controllo
Il pattern seguente è volutamente generico ma eseguibile sulla maggior parte dei warehouse moderni. Serve a costruire una base analitica con metrica, segmento e finestra temporale, così da confrontare periodi e gruppi senza riscrivere ogni volta la logica.
WITH base_events AS (
SELECT
user_id,
account_id,
event_type,
event_time,
DATE_TRUNC('week', event_time) AS week,
source,
device_type
FROM events
WHERE event_time >= CURRENT_DATE - INTERVAL '180 days'
AND user_id IS NOT NULL
),
weekly_user_metrics AS (
SELECT
week,
user_id,
COALESCE(source, 'unknown') AS source,
COALESCE(device_type, 'unknown') AS device_type,
COUNT(*) AS total_events,
COUNT(DISTINCT DATE(event_time)) AS active_days,
COUNT(DISTINCT event_type) AS event_diversity,
MAX(CASE WHEN event_type IN ('purchase', 'subscribe', 'activation') THEN 1 ELSE 0 END) AS reached_key_outcome
FROM base_events
GROUP BY week, user_id, source, device_type
)
SELECT
week,
source,
device_type,
COUNT(DISTINCT user_id) AS users,
ROUND(AVG(active_days), 2) AS avg_active_days,
ROUND(AVG(event_diversity), 2) AS avg_event_diversity,
ROUND(AVG(reached_key_outcome) * 100, 2) AS key_outcome_rate
FROM weekly_user_metrics
GROUP BY week, source, device_type
ORDER BY week, source, device_type;
La query non pretende di dare la risposta finale. Crea una superficie di osservazione fatta di trend, segmenti e differenze tra canali, da cui un analista può formulare ipotesi più precise.
Esempio Python: stabilità e anomalie
Una metrica utile deve essere abbastanza stabile da orientare le decisioni e abbastanza sensibile da segnalare cambiamenti reali. In Python si possono controllare le variazioni anomale settimana su settimana.
# df contiene: week, segment, users, key_outcome_rate
# key_outcome_rate espresso in percentuale, es. 12.4
df = df.sort_values(['segment', 'week']).copy()
df['previous_rate'] = df.groupby('segment')['key_outcome_rate'].shift(1)
df['wow_change_pp'] = df['key_outcome_rate'] - df['previous_rate']
df['rolling_mean'] = df.groupby('segment')['key_outcome_rate'].transform(
lambda s: s.rolling(4, min_periods=2).mean()
)
df['rolling_std'] = df.groupby('segment')['key_outcome_rate'].transform(
lambda s: s.rolling(4, min_periods=2).std()
)
df['z_score'] = (df['key_outcome_rate'] - df['rolling_mean']) / df['rolling_std']
anomalies = df[df['z_score'].abs() >= 2].sort_values('z_score')
print(anomalies[['week', 'segment', 'key_outcome_rate', 'wow_change_pp', 'z_score']])
Il valore di questo controllo è pratico: evita di reagire a ogni oscillazione casuale e segnala quando una variazione merita davvero un’indagine. Lo stesso meccanismo può alimentare alert, review settimanali e retrospettive di prodotto.
Errori comuni
Il primo errore è lavorare su dati aggregati troppo presto, perché una media globale può coprire due segmenti che vanno in direzioni opposte. Il secondo è non controllare la qualità del dato: eventi duplicati, tracking incompleto, timezone incoerenti e cambi di definizione producono conclusioni false con una facilità sorprendente. Il terzo è confondere correlazione e causalità, perché se gli utenti che usano una feature convertono di più non significa che la feature causi la conversione; potrebbero usarla proprio perché sono già più motivati.
Per ridurre questi rischi conviene tenere, in ogni analisi, almeno tre controlli minimi: una definizione esplicita della metrica, un confronto per segmento e una verifica contro un periodo precedente o un gruppo di controllo.
Riepilogo
Lo streaming con Kafka va trattato come uno strumento decisionale, non come un argomento da manuale. Il valore nasce quando colleghi problema, dati, metrica, segmentazione e azione, e quando ricordi che Kafka conviene solo dove la sua latenza e la sua riusabilità servono a qualcosa. Una buona analisi non si chiude con “il numero è salito” o “il numero è sceso”, ma con una frase operativa: quale decisione prendiamo, con quale confidenza, e quale metrica useremo per sapere se avevamo ragione.
Riferimenti:
- Kreps, J., Narkhede, N. & Rao, J. (2011). “Kafka: a Distributed Messaging System for Log Processing.” NetDB 2011.
- Confluent. (2024). “Apache Kafka Documentation.” kafka.apache.org/documentation.
Percorso collegato
Lezioni da leggere insieme
Questi collegamenti portano la lezione dentro il resto del corso: basi da riprendere, passaggi successivi e connessioni tematiche tra moduli.