La chiave è richiesta come parte dell'invio di messaggi a Kafka?


93
KeyedMessage<String, byte[]> keyedMessage = new KeyedMessage<String, byte[]>(request.getRequestTopicName(), SerializationUtils.serialize(message)); 
producer.send(keyedMessage);

Attualmente sto inviando messaggi senza alcuna chiave come parte di messaggi con chiave, funzionerà ancora delete.retention.ms? Devo inviare una chiave come parte del messaggio? È utile inserire la chiave come parte del messaggio?

Risposte:


172

Le chiavi sono per lo più utili / necessarie se hai bisogno di un ordine forte per una chiave e stai sviluppando qualcosa come una macchina a stati. Se richiedi che i messaggi con la stessa chiave (ad esempio, un ID univoco) siano sempre visualizzati nell'ordine corretto, allegare una chiave ai messaggi assicurerà che i messaggi con la stessa chiave vadano sempre nella stessa partizione in un argomento. Kafka garantisce l'ordine all'interno di una partizione, ma non tra le partizioni di un argomento, quindi, in alternativa, non fornire una chiave, che si tradurrà in una distribuzione round-robin tra le partizioni, non manterrà tale ordine.

Nel caso di una macchina a stati, le chiavi possono essere utilizzate con log.cleaner.enable per deduplicare le voci con la stessa chiave. In tal caso, Kafka presume che la tua applicazione si preoccupi solo dell'istanza più recente di una determinata chiave e il pulitore di log elimina i duplicati più vecchi di una determinata chiave solo se la chiave non è nulla. Questa forma di compattazione del registro è controllata dalla proprietà log.cleaner.delete.retention e richiede chiavi.

In alternativa, la proprietà più comune log.retention.hours , che è abilitata per impostazione predefinita, funziona eliminando segmenti completi del log che non sono aggiornati. In questo caso non è necessario fornire le chiavi. Kafka eliminerà semplicemente i blocchi del registro più vecchi del periodo di conservazione specificato.

Questo è tutto da dire, se hai abilitato la compattazione dei log o richiedi un ordine rigoroso per i messaggi con la stessa chiave, dovresti assolutamente usare le chiavi. In caso contrario, le chiavi null possono fornire una migliore distribuzione e prevenire potenziali problemi di hot spotting nei casi in cui alcune chiavi potrebbero apparire più di altre.


Sono nuovo a Kafka, questo è il motivo per cui faccio così tante domande: Ci sono un paio di domande su questo: Prima domanda, possiamo consumare il messaggio sulla base delle chiavi, Attualmente sto consumando il messaggio da MessagAndMetadata mm. o va bene ignorare la chiave al momento del consumo del messaggio. Sto usando l'API Consumer di alto livello.
gaurav

1
@kuujo Presumo che questa deduplicazione sia solo per le voci di registro, non necessariamente deduplica i messaggi su una coda di argomenti?
user1658296

2
@oblivion che i messaggi vadano nella stessa partizione in sequenza è importante per la gestione degli aggiornamenti non identici, ad esempio il cliente seleziona la data di consegna (un messaggio) ma cambia idea in seguito (secondo messaggio). Se i messaggi dovessero andare in partizioni diverse, uno dei messaggi potrebbe essere elaborato per primo / per ultimo, ad esempio con 2 utenti che consumano da ciascuna partizione. Se entrambi i messaggi relativi alla stessa consegna vanno nella stessa partizione, vengono elaborati first-in-first-out, fornendo la data di consegna finale corretta.
Kunal

3
Le garanzie dell'ordine non provengono dalla chiave ma dai messaggi che si trovano nella stessa partizione. L'instradamento dei messaggi alle partizioni non deve essere basato su chiavi. È possibile specificare esplicitamente una partizione durante la creazione di unProducerRecord
Malt

2
La mia comprensione è che il client produttore è responsabile della scelta della partizione ( kafka.apache.org/documentation.html#design_loadbalancing ), che può o non può essere basata sulla chiave. Allora perché dici che le chiavi sono necessarie per ordinare?
lfk

5

Oltre alla risposta accettata molto utile, vorrei aggiungere alcuni dettagli in più

Partizionamento

Per impostazione predefinita, Kafka utilizza la chiave del messaggio per selezionare la partizione dell'argomento in cui scrive. Questo viene fatto da qualcosa di simile

hash(key) % number_of_partitions

Se non viene fornita alcuna chiave, Kafka partizionerà i dati in modo casuale in modo round robin.

Ordinazione

Come indicato nella risposta data, Kafka ha garanzie sull'ordinamento dei messaggi solo a livello di partizione.

Supponiamo che tu voglia archiviare le transazioni finanziarie per i tuoi clienti in un argomento Kafka con due partizioni. I messaggi potrebbero apparire come (chiave: valore)

null:{"customerId": 1, "changeInBankAccount": +200}
null:{"customerId": 2, "changeInBankAccount": +100}
null:{"customerId": 1, "changeInBankAccount": +200}
null:{"customerId": 1, "changeInBankAccount": -1337}
null:{"customerId": 1, "changeInBankAccount": +200}

Poiché non abbiamo definito una chiave, le due partizioni presumibilmente saranno simili

// partition 0
null:{"customerId": 1, "changeInBankAccount": +200}
null:{"customerId": 1, "changeInBankAccount": +200}
null:{"customerId": 1, "changeInBankAccount": +200}

// partition 1
null:{"customerId": 2, "changeInBankAccount": +100}
null:{"customerId": 1, "changeInBankAccount": -1337}

Il tuo consumatore leggendo quell'argomento potrebbe finire per dirti che il saldo del conto è di 600 in un determinato momento, anche se non è mai stato così! Solo perché stava leggendo tutti i messaggi nella partizione 0 prima dei messaggi nella partizione 1.

Con una chiave sensata (come customerId) questo potrebbe essere evitato in quanto il partizionamento sarebbe come questo:

// partition 0
1:{"customerId": 1, "changeInBankAccount": +200}
1:{"customerId": 1, "changeInBankAccount": +200}
1:{"customerId": 1, "changeInBankAccount": -1337}
1:{"customerId": 1, "changeInBankAccount": +200}

// partition 1
2:{"customerId": 2, "changeInBankAccount": +100}

Compattazione del registro

Senza una chiave come parte dei tuoi messaggi, non sarai in grado di impostare la configurazione dell'argomento cleanup.policysu compacted. Secondo la documentazione, "la compattazione del registro garantisce che Kafka conserverà sempre almeno l'ultimo valore noto per ciascuna chiave di messaggio all'interno del registro dei dati per una singola partizione di argomento".

Questa impostazione piacevole e utile non sarà disponibile senza alcuna chiave.

Utilizzo delle chiavi

Nei casi d'uso della vita reale, la chiave di un messaggio Kafka può avere un'enorme influenza sulle tue prestazioni e sulla chiarezza della tua logica aziendale.

Ad esempio, una chiave può essere utilizzata naturalmente per partizionare i dati. Dato che puoi controllare i tuoi consumatori in modo che leggano da partizioni particolari, questo potrebbe servire come un filtro efficiente. Inoltre, la chiave può includere alcuni metadati sul valore effettivo del messaggio che consentono di controllare la successiva elaborazione. Le chiavi sono generalmente più piccole dei valori ed è quindi più conveniente analizzare una chiave anziché l'intero valore. Allo stesso tempo, puoi applicare tutte le serializzazioni e la registrazione dello schema come fatto con il tuo valore anche con la chiave.

Come nota, c'è anche il concetto di intestazione che può essere utilizzato per memorizzare le informazioni, vedere la documentazione .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.