Configurazione della Replica Kafka: Garantire Durabilità e Disponibilità dei Dati
Configura la replica Kafka, ISR, acknowledgment del produttore e consapevolezza dei rack senza indebolire la durabilità.
Configurazione della Replica Kafka: Garantire Durabilità e Disponibilità dei Dati
La configurazione della replica Kafka è il punto in cui un cluster smette di essere un mucchio di broker e inizia a comportarsi come un sistema di cui ci si può fidare durante i guasti. Le impostazioni non sono complicate di per sé: fattore di replica, repliche in-sync, acknowledgment del produttore, elezione del leader e posizionamento nei rack. La parte difficile è che hanno senso solo insieme.
Un topic con tre repliche può comunque perdere dati riconosciuti se i produttori usano acknowledgment deboli. Un produttore che usa acks=all può comunque fallire le scritture se min.insync.replicas è troppo restrittivo per il numero di broker attualmente attivi. Un cluster distribuito tra zone di disponibilità può comunque avere una brutta giornata se tutte le repliche per una partizione calda finiscono nello stesso dominio di guasto. La replica non è una singola casella da spuntare.
Il modo in cui mi piace pensare alla replica Kafka è semplice: per ogni partizione, Kafka mantiene diverse copie, sceglie una copia per accettare letture e scritture, e mantiene le altre copie abbastanza vicine in modo che una di esse possa subentrare. Il tuo compito è decidere quante copie sono sufficienti, quante devono essere aggiornate prima che una scrittura sia considerata riuscita, e se il cluster debba mai preferire la disponibilità alla sicurezza dei dati.
Un topic Kafka è suddiviso in partizioni. Ogni partizione ha una replica leader e zero o più repliche follower. I produttori scrivono sul leader. I consumatori normalmente leggono dal leader. I follower recuperano i record dal leader e mantengono allineati i loro log locali. Se il broker del leader fallisce, Kafka elegge un nuovo leader tra le repliche considerate candidate sicure.
Quell'elenco di candidati sicuri è l'ISR, acronimo di in-sync replicas. Una replica è nell'ISR quando si mantiene al passo con il leader abbastanza strettamente secondo le regole di ritardo della replica di Kafka. Se un follower smette di recuperare, rimane indietro per troppo tempo, o il broker scompare, Kafka lo rimuove dall'ISR. Quando recupera, può rientrare.
Questo dettaglio è importante perché l'ISR è ciò che rende la durabilità di Kafka più di un pio desiderio. Con acks=all, il leader non riconosce una richiesta di produzione finché il record non è stato replicato sulle repliche in-sync richieste. Il requisito esatto è controllato da min.insync.replicas. Se il topic ha replication.factor=3 e min.insync.replicas=2, Kafka richiede almeno due repliche in-sync prima che una scrittura con acks=all possa avere successo.
Questa combinazione è comune in produzione perché offre un equilibrio pratico. Un broker può fallire e il topic può ancora accettare scritture fortemente riconosciute. Se un secondo broker fallisce prima che il primo torni, i produttori che usano acks=all dovrebbero iniziare a vedere errori come NotEnoughReplicas o NotEnoughReplicasAfterAppend. Questo è fastidioso durante un incidente, ma di solito è il comportamento corretto. Kafka si rifiuta di fingere che una scrittura sia duratura quando non ci sono abbastanza copie sicure.
Ecco la baseline di produzione tipica per un cluster normale di tre o più broker:
default.replication.factor=3
min.insync.replicas=2
unclean.leader.election.enable=false
Questi valori non rendono automaticamente sicuro ogni carico di lavoro, ma offrono un punto di partenza sensato. default.replication.factor=3 significa che i nuovi topic ottengono tre copie a meno che il comando di creazione del topic non dica diversamente. min.insync.replicas=2 significa che almeno due repliche devono essere in-sync per scritture forti. unclean.leader.election.enable=false dice a Kafka di non eleggere una replica obsoleta come leader solo per mantenere una partizione scrivibile.
Non impostare il fattore di replica più alto del numero di broker. Kafka non può posizionare tre repliche su tre broker diversi se esistono solo due broker. Nei piccoli cluster di sviluppo, replication.factor=1 va bene perché la comodità conta più della tolleranza ai guasti. In produzione, 1 significa che la perdita di un singolo broker può rendere i dati non disponibili e può perdere permanentemente i record memorizzati solo su quel broker.
Il lato produttore deve corrispondere al lato topic. Per dati importanti, usa acks=all. Abilita anche l'idempotenza a meno che tu non abbia una ragione specifica per non farlo. Nei client Kafka moderni, i produttori idempotenti sono la scelta normale per ridurre i duplicati causati dai tentativi.
acks=all
enable.idempotence=true
retries=2147483647
max.in.flight.requests.per.connection=5
Non copiare ciecamente il valore di retry in ogni client senza comprendere la versione del client e i requisiti di consegna. L'idea importante è che la produzione Kafka durevole di solito necessita di tentativi, idempotenza e acks=all insieme. Se imposti acks=1, il leader può riconoscere un record prima che i follower lo abbiano copiato. Se quel leader muore al momento sbagliato, un record riconosciuto può scomparire. Questo è accettabile per alcuni flussi di telemetria. Non è accettabile per pagamenti, tracce di audit, movimenti di inventario o qualsiasi cosa che un team a valle tratti come fonte di verità.
Quando crei un topic, imposta le scelte di replica deliberatamente invece di affidarti ai valori predefiniti del broker che potrebbero essere presenti:
kafka-topics.sh --create --bootstrap-server broker1:9092 --topic orders.v1 --partitions 12 --replication-factor 3 --config min.insync.replicas=2
Il numero di partizioni è separato dalla replica. Dodici partizioni con fattore di replica tre significano trentasei repliche di partizione in totale. Questo ha costi di archiviazione, rete, handle di file e metadati del controller. La replica migliora la durabilità, ma non è gratuita.
Per i topic esistenti, cambiare min.insync.replicas è semplice:
kafka-configs.sh --alter --bootstrap-server broker1:9092 --entity-type topics --entity-name orders.v1 --add-config min.insync.replicas=2
Cambiare il fattore di replica per un topic esistente dipende dalla versione di Kafka e dagli strumenti. Le versioni più recenti di Kafka supportano kafka-reassign-partitions.sh e, in alcuni casi, flussi di lavoro di alterazione dei topic che rendono più facili gli aumenti. Nei cluster più vecchi, aumentare la replica di solito significa generare ed eseguire un piano di riassegnazione delle partizioni. Diminuire la replica è più delicato perché stai rimuovendo copie. Trattalo come un'operazione pianificata, non un comando casuale digitato durante un incidente rumoroso.
Una riassegnazione dovrebbe essere limitata se il topic è grande o il cluster è già occupato. Il recupero della replica legge i vecchi dati dalle repliche esistenti e li scrive su quelle nuove. Questo può rubare capacità del disco e della rete dai produttori e consumatori attivi. Un runbook sicuro di solito include una finestra di manutenzione, output --describe prima e dopo, limiti di riassegnazione e un piano di rollback.
Puoi ispezionare un topic in questo modo:
kafka-topics.sh --describe --bootstrap-server broker1:9092 --topic orders.v1
Guarda tre campi nell'output: Leader, Replicas e Isr. Replicas è l'insieme assegnato. Isr è l'insieme attualmente aggiornato. Se Replicas è 1,2,3 ma Isr è 1,2, il broker 3 è indietro o non disponibile per quella partizione. Se molte partizioni mostrano un broker mancante nell'ISR, controlla il disco, la rete, la salute del processo e i log di quel broker. Se solo poche partizioni calde sono interessate, il leader potrebbe essere sovraccarico o la partizione potrebbe avere un traffico insolitamente alto.
L'elezione sporca del leader merita attenzione speciale. Se tutte le repliche in-sync per una partizione sono scomparse, Kafka ha due scelte. Può lasciare la partizione non disponibile finché una replica sicura non torna, oppure può eleggere una replica non in-sync e rischiare di perdere record che erano stati riconosciuti sul vecchio leader. unclean.leader.election.enable=false sceglie la sicurezza. true sceglie la disponibilità a rischio di perdita di dati.
Ci sono carichi di lavoro in cui l'elezione sporca può essere difendibile: dati di clickstream di breve durata, metriche usa e getta, o una pipeline in cui i sistemi a monte possono riprodurre tutto. Per la maggior parte dei dati aziendali, lascialo disabilitato. Perdere la disponibilità per una partizione è doloroso, ma la perdita silenziosa di dati è peggiore perché i consumatori potrebbero continuare come se nulla fosse successo.
La replica consapevole dei rack aiuta con una diversa classe di guasti. Se i tuoi broker sono suddivisi tra rack, zone o host con percorsi di alimentazione/rete condivisi, dì a Kafka dove vive ogni broker:
broker.rack=zone-a
Imposta il valore corretto su ogni broker. Kafka cercherà di distribuire le repliche tra i rack in modo che un singolo guasto di zona abbia meno probabilità di rimuovere ogni copia di una partizione. Questo non è magia. Hai ancora bisogno di abbastanza broker in ogni zona, abbastanza disco e un posizionamento attento delle partizioni. Ma senza broker.rack, Kafka non ha modo di sapere che due broker condividono lo stesso dominio di guasto.
Monitora la replica continuamente. I segnali di allarme precoce più utili sono partizioni sotto-replicate, partizioni offline, eventi di restringimento dell'ISR ed errori di produzione relativi a repliche insufficienti. Nelle configurazioni basate su Prometheus, i team guardano comunemente le metriche dei broker Kafka per partizioni sotto-replicate e partizioni offline, quindi abbinano questi avvisi con metriche del disco, della rete e JVM del broker.
Una buona domanda durante un incidente è: l'ISR si è ristretto perché un broker è morto, perché la replica non riesce a tenere il passo, o perché la rete è inaffidabile? La soluzione è diversa. Un broker morto necessita di ripristino del servizio. Un broker lento può necessitare di sostituzione del disco, indagine I/O o meno leader di partizione. Un problema di rete può manifestarsi come disconnessioni ripetute e ritardo del fetcher anche quando CPU e disco sembrano a posto.
I riavvii rolling dei broker sono un altro punto in cui le impostazioni di replica mostrano il loro valore. Riavvia un broker alla volta. Aspetta che le partizioni recuperino un ISR sano prima di riavviare il broker successivo. Se riavvii i broker troppo velocemente con min.insync.replicas=2, i produttori potrebbero iniziare a fallire perché troppo poche repliche sono in-sync. Quel fallimento è previsto, ma puoi evitarlo con pazienza e monitoraggio.
La checklist pratica è breve. Usa fattore di replica tre per la maggior parte dei topic di produzione. Usa min.insync.replicas=2 con il produttore acks=all per dati importanti. Mantieni disabilitata l'elezione sporca del leader a meno che i dati non siano esplicitamente usa e getta. Distribuisci le repliche tra domini di guasto con la consapevolezza dei rack. Controlla la salute dell'ISR, non solo l'uptime del broker. E testa le tue ipotesi riavviando un broker in una finestra controllata prima che un vero guasto lo faccia per te.
Un dettaglio che aiuta durante le revisioni è separare durabilità e disponibilità in linguaggio semplice. La durabilità chiede: "Dopo che Kafka dice che la scrittura è riuscita, quanti guasti possono accadere prima che quel record riconosciuto sia a rischio?" La disponibilità chiede: "I produttori e i consumatori possono ancora usare la partizione in questo momento?" Impostazioni forti a volte riducono la disponibilità perché Kafka rifiuterà le scritture piuttosto che accettare dati debolmente replicati. Questo non è un fallimento di Kafka. Questo è Kafka che onora il contratto che hai configurato.
Ad esempio, immagina un topic con fattore di replica tre, min.insync.replicas=2 e produttori che usano acks=all. Il broker 1 è leader, i broker 2 e 3 sono follower. Se il broker 3 va giù, l'ISR diventa 1,2. Le scritture hanno ancora successo perché due repliche sono in-sync. Se il broker 2 poi va giù prima che il broker 3 torni, l'ISR diventa solo 1. Le scritture falliscono. Alcuni team vedono questo per la prima volta in produzione e chiedono perché Kafka è giù quando il leader è ancora vivo. La risposta è che il topic è ancora disponibile per alcune letture, ma non è sicuro per scritture fortemente riconosciute.
Dovresti anche pensare al recupero dei consumatori. La replica protegge le copie lato broker dei record. Non protegge automaticamente gli offset dei consumatori da ogni errore del flusso di lavoro. Gli offset dei consumatori sono memorizzati anche in Kafka, di solito in __consumer_offsets, quindi anche quel topic interno necessita di una replica sana. Se i topic utente sono configurati attentamente ma i topic interni sono stati creati con replica debole in una build iniziale del cluster, il comportamento di failover può comunque essere peggiore del previsto. Controlla la replica dei topic interni come parte di una revisione di prontezza alla produzione.
Nei cluster multi-tenant, non tutti i topic meritano la stessa configurazione. Un topic di metriche usa e getta con alto volume e basso valore aziendale può usare una retention più breve e tollerare garanzie più deboli. Un topic di fatturazione no. L'errore è lasciare che i valori predefiniti accidentali decidano questa distinzione. Metti per iscritto le classi di topic: flussi di eventi critici, telemetria riproducibile, topic di stato compattati, topic di sviluppo temporanei. Quindi mappa ogni classe su replica, ISR, retention e impostazioni del produttore.
Durante gli incidenti, evita di cambiare le impostazioni di durabilità solo per silenziare gli errori a meno che tutti non comprendano il compromesso. Abbassare min.insync.replicas da 2 a 1 può far muovere i produttori, ma significa anche che le scritture riconosciute possono vivere su un solo broker. Abilitare l'elezione sporca del leader può ripristinare la disponibilità della partizione, ma le repliche obsolete possono perdere record. A volte l'azienda può scegliere quel compromesso. Dovrebbe essere una decisione consapevole durante un incidente, non una scorciatoia nascosta dell'operatore.