Go to main content
Cheat Sheet — Kafka and Stream Processing - official lesson image on GinnyTech, created by AD

Cheat Sheet — Kafka and Stream Processing

Quick operational reference for Kafka: commands, configurations, and main patterns.

AD
Created byAndrii Dyshkantiuk
Lesson 118 / 236Level: AdvancedDuration: 10 minPrerequisites: 1

What you will learn

  • Understand the analytical problem and the decision-making context
  • Apply examples, metrics, and controls to real cases

import pandas as pd

Cheat sheet: Kafka e stream processing

Prima di aprire una pull request su una pipeline Kafka, ci sono domande pratiche a cui il team deve poter rispondere in fretta: chi possiede il topic, qual è la chiave, quale schema è compatibile, quanto dura la retention, quali consumer sono critici e come si misura il lag. Questa pagina raccoglie quei controlli in forma operativa, da usare come lista di revisione più che come lettura lineare. Ogni voce dovrebbe produrre una decisione verificabile: se non lo fa, resta un promemoria elegante e inutile.

Come usare questa pagina

La sequenza naturale di una review prima del rilascio tocca, nell’ordine, il design dei topic, i producer, i consumer, gli schemi, i connector, lo stream processing e le operations. Per ogni blocco conviene chiedersi quale regola serve sotto pressione, quale eccezione è facile dimenticare e quale controllo useresti domani su un progetto reale. Il resto della pagina segue grosso modo questa traccia.

Essential CLI Commands

# Creare un topic
kafka-topics --create --topic user-events --partitions 16 --replication-factor 3

# Lista consumer groups e lag
kafka-consumer-groups --bootstrap-server localhost:9092 --list
kafka-consumer-groups --describe --group my-group

# Leggere messaggi
kafka-console-consumer --topic user-events --from-beginning --max-messages 10

Sono i comandi che servono per le tre domande più frequenti durante un incidente: come è fatto il topic, quanto sono indietro i consumer e cosa contengono davvero i messaggi.

Recommended Producer Configurations

acks=all                     # maximum durability
enable.idempotence=true      # deduplicate retries
compression.type=zstd        # maximum compression
linger.ms=5                  # batching
batch.size=65536             # 64KB batch

La combinazione di acks=all e idempotenza è quella che protegge dai duplicati nei retry senza sacrificare la durabilità. Il batching con linger.ms e batch.size è il margine su cui si gioca il throughput, e va calibrato sul carico reale.

Recommended Consumer Configurations

group.id=analytics-team
auto.offset.reset=earliest   # leggi tutto se nuovo gruppo
enable.auto.commit=false     # commit manuale
max.poll.records=500         # batch gestibile

Il commit manuale è la scelta da preferire in produzione, perché il commit automatico può confermare offset di messaggi che non hai ancora processato davvero, con perdita silenziosa di dati in caso di crash.

Metrics to Monitor

MetricMeaningAlert if
Under-replicated partitionsBroker not in sync>0 for >1 minute
Consumer lag increasingConsumer not keeping upLag grows linearly
Disk free <30%Risk of filling upPlan expansion

Un lag che cresce in modo lineare è il segnale che il consumer non recupererà da solo: prima o poi serve più capacità o un fix nel processamento.

Serialization Patterns

JSON va bene per lo sviluppo rapido e il debugging, ma non garantisce uno schema. Avro con lo Schema Registry è la scelta da produzione quando servono contratti forti ed evoluzione sicura degli schemi. Protobuf dà la performance migliore e si usa tipicamente per la comunicazione gRPC tra servizi interni. La regola pratica è semplice: se il dato attraversa team o sopravvive nel tempo, vuoi uno schema registrato.

Anti-pattern da evitare

Un topic con una sola partizione e retention infinita è un collo di bottiglia che non scala e cresce senza limite. Lasciare enable.auto.commit=true in produzione espone alla perdita silenziosa di messaggi. Una chiave null su un topic compattato impedisce la compattazione e va contro lo scopo del topic stesso. E assumere un ordine globale dei messaggi tra partizioni diverse porta a bug sottili, perché Kafka garantisce l’ordine solo dentro la singola partizione.

Come impostare la scelta

La domanda di fondo, prima di toccare la configurazione, non è “quale parametro imposto” ma “quale decisione operativa devo rendere più sicura”. Conviene rendere esplicita l’unità di lavoro su cui ragioni (topic, evento, schema, producer, consumer o stream processor), il segnale che osservi (latenza, throughput, lag, compatibilità schema, perdita dati), la baseline rispetto a cui lo leggi e la decisione attesa, che sia un contratto evento, una pipeline o una policy. Il rischio costante è scambiare un numero disponibile per una prova sufficiente.

Un modo ordinato di lavorare segue questi passi:

  1. definire il problema in linguaggio di business;
  2. identificare l’unità di analisi corretta;
  3. controllare se i dati misurano il fenomeno o solo una sua ombra;
  4. build an interpretable metric;
  5. segment to avoid the average hiding opposite patterns;
  6. turn the result into a verifiable recommendation.

Un caso di review

Durante una review, la cheat sheet fa emergere che nessuno ha definito retention e owner di un topic usato da tre consumer. Il rilascio viene corretto prima della produzione, e questo significa meno urgenze in incident room e più decisioni prese quando il sistema è ancora facile da modificare. È esattamente il tipo di problema che una lista di controllo intercetta e che un occhio distratto lascia passare.

La lettura dei segnali resta prudente. Se un numero migliora, può essere un effetto reale o una normale variazione, e conviene cercare un confronto e un segmento. Se un solo segmento cambia più degli altri, la media aggregata nasconde una differenza. Se il costo cresce insieme al risultato, l’impatto va letto sul margine.

Esempio SQL: una vista di controllo

Il pattern seguente è generico ma eseguibile sulla maggior parte dei warehouse moderni. Serve a creare 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 dà la risposta finale: crea una superficie di osservazione fatta di trend, segmenti e differenze tra canali, da cui 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 è pratico: il controllo evita di reagire a ogni oscillazione casuale e segnala solo le variazioni che meritano un’indagine. Lo stesso meccanismo può alimentare alert, review settimanali e retrospettive di prodotto.

Kafka è il sistema nervoso dei dati di molte aziende: i producer scrivono, i consumer leggono, Connect integra, Streams trasforma e lo Schema Registry garantisce i contratti. Buona parte dei disastri si previene con un monitoraggio attento, perché qui la maggior parte dei problemi nasce dalla configurazione più che dal codice. Usa questa cheat sheet come lista di revisione: ogni voce vale solo se produce una decisione verificabile, e una buona analisi non si chiude con “il numero è cambiato” ma con quale scelta prendi e con quale metrica saprai se avevi ragione.