Padroneggiare la Configurazione dei Topic Kafka: Una Guida Completa

Una guida pratica alle partizioni, replicazione, conservazione, compattazione e modifiche sicure della configurazione dei topic Kafka.

Padroneggiare la Configurazione dei Topic Kafka: Una Guida Completa

La configurazione dei topic Kafka determina come i tuoi dati vengono memorizzati, copiati, scaduti, compattati e consumati. Puoi eseguire Kafka con le impostazioni predefinite per un po', specialmente in un cluster di sviluppo, ma i topic di produzione richiedono più attenzione. Un numero errato di partizioni può intrappolare un carico di lavoro intenso. Una replicazione debole può trasformare un guasto di un broker in una perdita di dati. Una conservazione lasca può riempire i dischi. La compattazione può sorprenderti se le chiavi sono mancanti o inconsistenti.

Il modo utile per affrontare la configurazione dei topic Kafka non è memorizzare ogni impostazione. Inizia con le domande che un sistema reale pone: di quanto parallelismo ho bisogno, per quanto tempo i dati devono rimanere disponibili, quanti dati posso permettermi di memorizzare, cosa succede durante un guasto di un broker e i consumatori hanno bisogno di una cronologia completa degli eventi o solo dell'ultimo valore per chiave?

Un topic è suddiviso in partizioni. Ogni partizione è un log ordinato. Kafka preserva l'ordine all'interno di una partizione, non nell'intero topic. Se tutti gli eventi per un cliente devono essere elaborati in ordine, usa una chiave stabile come customer_id in modo che quegli eventi finiscano nella stessa partizione. Se usi chiavi casuali, potresti ottenere una migliore distribuzione ma perdere l'ordinamento per entità.

Il numero di partizioni è una delle prime scelte di cui le persone si pentono. Più partizioni consentono un maggiore parallelismo dei consumatori perché, all'interno di un gruppo di consumatori, una partizione viene consumata da un solo membro del gruppo alla volta. Se un topic ha sei partizioni, un gruppo di consumatori può utilizzare attivamente fino a sei consumatori per quel topic. Aggiungere un settimo consumatore non aumenterà il consumo per quel topic a meno che non ci siano altre partizioni assegnate.

Più partizioni hanno anche un costo. Aumentano i metadati, i file aperti, il lavoro di replicazione, il lavoro di elezione del leader e il tempo di recupero dopo i guasti dei broker. Conteggi di partizioni molto elevati possono rallentare le operazioni del cluster anche se ogni partizione ha un traffico modesto. Non esiste un numero migliore universale. Un piccolo topic interno può andare bene con tre partizioni. Un flusso di eventi intenso può necessitare di dozzine. Un'installazione Kafka molto grande può usarne molti di più, ma ciò dovrebbe derivare da una capacità di throughput misurata e operativa, non dall'abitudine.

Crea un topic con impostazioni esplicite:

kafka-topics.sh --create   --bootstrap-server broker1:9092   --topic user-events.v1   --partitions 12   --replication-factor 3   --config min.insync.replicas=2

Il nome del topic dovrebbe anche trasmettere un intento. Nomi come events o data diventano inutili una volta che il cluster cresce. user-events.v1, billing-invoices.v1 o inventory-adjustments.v1 dice ai futuri operatori qual è il flusso e ti dà spazio per una modifica dello schema che rompe la compatibilità in seguito.

Il fattore di replicazione controlla quante copie Kafka mantiene per ogni partizione. In produzione, 3 è un valore predefinito comune perché consente il guasto di un broker lasciando comunque disponibile un'altra replica. Non significa che puoi ignorare le impostazioni del produttore. Se i produttori usano acks=1, Kafka può riconoscere i record prima che i follower li abbiano copiati. Per topic importanti, abbina il fattore di replicazione tre con min.insync.replicas=2 a livello di topic e acks=all del produttore.

min.insync.replicas è spesso frainteso. Non crea repliche. Dice quante repliche in-sync devono essere disponibili affinché una scrittura con acks=all abbia successo. Con fattore di replicazione tre e min.insync.replicas=2, il topic può tollerare che un broker non sia disponibile. Se rimane solo una replica in-sync, Kafka dovrebbe rifiutare le scritture forti invece di accettare dati con troppo poche copie sicure.

Le impostazioni di conservazione decidono quando Kafka può eliminare i vecchi segmenti di log. La conservazione basata sul tempo è controllata da retention.ms a livello di topic. La conservazione basata sulla dimensione è controllata da retention.bytes. Nomi più vecchi a livello di broker come log.retention.ms sono valori predefiniti del broker; la configurazione del topic usa comunemente retention.ms.

Ad esempio, per conservare un topic per sette giorni:

kafka-configs.sh --alter   --bootstrap-server broker1:9092   --entity-type topics   --entity-name user-events.v1   --add-config retention.ms=604800000

Per limitare l'archiviazione per partizione, usa retention.bytes:

kafka-configs.sh --alter   --bootstrap-server broker1:9092   --entity-type topics   --entity-name user-events.v1   --add-config retention.bytes=10737418240

Ricorda che retention.bytes è solitamente per partizione, non per dimensione totale del topic. Un topic con dodici partizioni e retention.bytes=10GB può utilizzare circa 120 GB prima della replicazione e circa 360 GB con fattore di replicazione tre. Questo è il tipo di dettaglio che causa avvisi di disco sorprendenti.

Kafka elimina i dati per segmento di log, non record per record. Se imposti un breve periodo di conservazione ma segmenti grandi, l'eliminazione potrebbe non avvenire al minuto esatto che ti aspetti. Impostazioni di segmento come segment.bytes e segment.ms influenzano quando Kafka passa a un nuovo segmento e solo i segmenti chiusi sono idonei per l'eliminazione o la compattazione. Segmenti più piccoli possono rendere la pulizia più reattiva, ma aggiungono overhead.

cleanup.policy decide cosa fa Kafka con i vecchi dati. Il valore predefinito è delete, che rimuove i vecchi segmenti in base alla conservazione. compact mantiene l'ultimo record per ogni chiave e alla fine rimuove i record più vecchi con la stessa chiave. Puoi anche usare delete,compact per topic che necessitano di compattazione più una finestra di conservazione.

La compattazione è utile per flussi di tipo stato: aggiornamenti del profilo utente, valori di flag di funzionalità, impostazioni dell'account o eventi di modifica del database con chiave primaria. È una scelta inadeguata per la cronologia degli eventi in cui ogni evento conta. Se compatti un log di audit, gli eventi più vecchi per la stessa chiave potrebbero alla fine scomparire. Questo potrebbe essere esattamente sbagliato per conformità o debug.

La compattazione dipende anche dalle chiavi. Un topic compattato con chiavi nulle o inconsistenti non si comporterà come un changelog chiave-valore pulito. Se i produttori inviano aggiornamenti utente a volte con chiave user_id e a volte con chiave email, Kafka vede chiavi diverse. Non può dedurre che rappresentano lo stesso utente.

La compressione può essere impostata dai produttori e un topic può definire compression.type per controllare il comportamento del broker. I valori comuni includono producer, gzip, snappy, lz4 e zstd, a seconda della versione di Kafka. Molti team lasciano il topic a producer e standardizzano la compressione del produttore. lz4 e zstd sono scelte comuni, ma la risposta giusta dipende dal budget della CPU, dalla forma del messaggio e dalla pressione della rete.

Puoi ispezionare la configurazione del topic in questo modo:

kafka-configs.sh --describe   --bootstrap-server broker1:9092   --entity-type topics   --entity-name user-events.v1

E ispezionare il posizionamento delle partizioni in questo modo:

kafka-topics.sh --describe   --bootstrap-server broker1:9092   --topic user-events.v1

Usa entrambi i comandi. Le configurazioni del topic ti dicono le regole di conservazione, compattazione e ISR. La descrizione del topic ti dice leader, repliche e stato ISR. Un topic può avere una configurazione perfetta ed essere comunque non sano perché le repliche non sono sincronizzate.

Alcune modifiche sono facili. La conservazione, la politica di compattazione, min.insync.replicas e molte altre configurazioni del topic possono essere modificate dinamicamente. Alcune modifiche richiedono più cautela. Puoi aumentare il numero di partizioni, ma non puoi diminuirlo in sicurezza con un semplice comando. Aumentare le partizioni cambia anche la distribuzione delle chiavi per i record futuri perché il calcolo del partizionamento ha più partizioni di destinazione. I record esistenti rimangono dove sono; i nuovi record per la stessa chiave potrebbero andare a una partizione diversa dopo l'aumento, a seconda del partizionatore. Se l'ordinamento rigoroso per chiave attraverso la modifica è importante, pianifica attentamente.

Le modifiche al fattore di replicazione sono lavoro operativo. Aumentare le repliche per un topic esistente significa che Kafka deve copiare i dati esistenti su nuovi broker. Questo può essere molto I/O. Usa strumenti di riassegnazione, monitora i progressi e limita se necessario. Non avviare una grande riassegnazione durante il traffico di punta a meno che tu non sappia già che il cluster ha abbastanza capacità di riserva.

Per un topic di eventi di produzione normale, un punto di partenza pratico potrebbe assomigliare a questo:

kafka-topics.sh --create   --bootstrap-server broker1:9092   --topic payments-authorized.v1   --partitions 24   --replication-factor 3   --config min.insync.replicas=2   --config retention.ms=1209600000   --config cleanup.policy=delete

Questo dice: abbastanza partizioni per il parallelismo, tre copie per la disponibilità, due repliche in-sync richieste per scritture forti, quattordici giorni di conservazione e nessuna compattazione perché ogni evento di autorizzazione del pagamento conta.

Per un topic di stato, la forma è diversa:

kafka-topics.sh --create   --bootstrap-server broker1:9092   --topic user-preferences.v1   --partitions 12   --replication-factor 3   --config min.insync.replicas=2   --config cleanup.policy=compact

Questo topic dovrebbe essere chiave per ID utente. I consumatori che ricostruiscono lo stato possono leggere il log compattato e alla fine vedere l'ultimo valore per ogni utente. Non dovrebbero aspettarsi che ogni modifica storica delle preferenze rimanga per sempre.

La migliore configurazione del topic è noiosa da gestire. Ha abbastanza partizioni ma non migliaia senza motivo. Ha una replicazione che corrisponde al valore dei dati. Ha una conservazione che corrisponde alle esigenze di recupero e conformità. Usa la compattazione solo quando le chiavi sono significative. È descritta nel codice o nella documentazione in modo che un altro ingegnere possa ricrearla senza indovinare.

Un'abitudine di revisione utile è scrivere la storia del consumatore prima di scegliere le impostazioni del topic. Chi legge questo topic? Hanno bisogno di riprodurre dall'inizio? Quanto tempo richiederebbe una ricostruzione completa? Il sistema di origine può ripubblicare i vecchi dati? Se un consumatore è giù per tre giorni, Kafka dovrebbe ancora avere i record persi? Quelle risposte guidano la conservazione in modo più onesto di un'impostazione predefinita di sette giorni.

Considera un consumatore di rilevamento frodi che legge eventi di pagamento. Se è giù per sei ore, quasi certamente vuoi che recuperi da Kafka. Se è giù per trenta giorni, potresti aspettarti un processo di backfill separato dal database dei pagamenti. Quel topic potrebbe aver bisogno di due settimane di conservazione, non per sempre. Un topic di audit di sicurezza potrebbe avere un requisito diverso, forse l'invio a un archivio di oggetti per la conservazione a lungo termine mentre Kafka mantiene solo la finestra di riproduzione calda.

La dimensione del messaggio appartiene anche alla conversazione del topic. Kafka può gestire record più grandi quando configurato per farlo, ma i messaggi grandi influenzano produttori, broker, consumatori, replicazione e memoria di recupero. Se i team iniziano a mettere blob JSON multi-megabyte o file codificati in un topic, non limitarti ad aumentare max.message.bytes e proseguire. Chiediti se il payload appartiene all'archivio di oggetti con un riferimento in Kafka. Kafka è solitamente il migliore per spostare eventi, non per agire come un archivio di blob.

L'evoluzione dello schema non è un'impostazione di configurazione del topic, ma modella la progettazione del topic. Un topic denominato con un suffisso di versione, come orders.v1, ti dà una via di fuga quando una modifica che rompe la compatibilità è inevitabile. Le modifiche compatibili possono rimanere nello stesso topic se consumatori e produttori seguono una politica dello schema. Le modifiche che rompono la compatibilità non dovrebbero essere introdotte nello stesso topic perché un team controlla il produttore. Kafka disaccoppia i sistemi, ma solo se il contratto è rispettato.

Infine, documenta la proprietà del topic. Ogni topic di produzione dovrebbe avere un team proprietario, produttori previsti, consumatori previsti, motivo di conservazione e note sulla sensibilità dei dati. Questo sembra amministrativo finché il disco non si riempie alle 02:00 e nessuno sa se un topic può essere accorciato, eliminato, compattato o limitato. Una buona configurazione del topic è in parte tecnica e in parte memoria operativa.

Un controllo finale prima di pubblicare un topic è eseguire uno scenario di guasto. Se un broker scompare, i produttori possono ancora scrivere? Se un gruppo di consumatori è giù per il fine settimana, la conservazione coprirà il divario? Se un produttore invia dati errati, i consumatori possono saltare, mettere in quarantena o riprodurre in sicurezza? Se il topic cresce due volte più velocemente del previsto, quale limite protegge il cluster: tempo di conservazione, byte di conservazione, quote o un avviso?

Le quote meritano una menzione perché la sola configurazione del topic non protegge un cluster condiviso da un produttore rumoroso. Kafka supporta quote client che possono limitare i tassi di produzione e recupero. Se diversi team condividono un cluster, le quote possono impedire che una riproduzione accidentale o un produttore fuori controllo sopraffacciano i broker. Dovrebbero essere abbinate ad avvisi in modo che i team sappiano di essere limitati invece di incolpare silenziosamente Kafka.

Non dimenticare la politica di eliminazione. Alcuni cluster disabilitano l'eliminazione dei topic a livello di broker per prevenire incidenti. Questo può essere sensato, ma significa che i topic abbandonati devono essere gestiti attraverso un processo di pulizia controllato. Una revisione dell'inventario dei topic ogni mese o trimestre può recuperare una quantità sorprendente di spazio su disco, specialmente nei cluster di sviluppo e staging dove gli esperimenti lasciano vecchi topic.