2016-03-24 23 views
21

Kafka suddivide i messaggi in entrata in partizioni, in base alla partizione assegnata dal produttore. I messaggi dalle partizioni vengono quindi consumati dai consumatori in diversi gruppi di consumatori.Apache Kafka è appropriato per l'uso come coda di attività?

Questa architettura mi rende cauto nell'usare Kafka come coda lavoro/attività, perché devo specificare la partizione al momento della produzione, il che limita indirettamente i consumatori su cui può lavorare perché una partizione viene inviata a un solo utente in un gruppo di consumatori. Preferirei non specificare la partizione prima del tempo, in modo tale che qualsiasi consumatore sia disponibile a svolgere quell'attività può farlo. C'è un modo per strutturare partizioni/produttori in un'architettura di Kafka in cui le attività possono essere tirate dal prossimo consumatore disponibile, senza dover suddividere il lavoro in anticipo scegliendo una partizione quando il lavoro viene prodotto?

L'utilizzo di una sola partizione per questo argomento mette tutte le attività nella stessa coda, ma il numero di utenti è limitato a 1 per gruppo di consumatori, pertanto ciascun consumatore dovrebbe trovarsi in un gruppo diverso. Quindi, tutte le attività vengono distribuite a ciascun gruppo di utenti, il che non è il tipo di coda di lavoro che sto cercando.

Apache Kafka è appropriato per l'uso come coda di attività?

risposta

16

L'utilizzo di Kafka per una coda di attività è una cattiva idea. Usa RabbitMQ invece, lo fa molto meglio e più elegantemente.

Sebbene sia possibile utilizzare Kafka per una coda di attività, si otterranno alcuni problemi: Kafka non consente di utilizzare una singola partizione da molti utenti (in base alla progettazione), quindi se ad esempio una singola partizione viene riempita con molte attività e il consumatore che possiede la partizione è occupato, le attività in quella partizione avranno "fame". Ciò significa anche che l'ordine di consumo delle attività nell'argomento non sarà identico all'ordine in cui sono state prodotte le attività che potrebbero causare seri problemi se le attività devono essere consumate in un ordine specifico (in Kafka per ottenere pienamente che tu deve avere un solo consumatore e una sola partizione - il che significa un consumo seriale di un solo nodo. Se si hanno più utenti e più partizioni, l'ordine delle attività di consumo non sarà garantito a livello di argomento).

In effetti, gli argomenti di Kafka non sono code in modo informatico. Queue significa First in First out - questo non è ciò che ottieni in Kafka a livello di argomento.

Un altro problema è che è difficile modificare il numero di partizioni in modo dinamico. Aggiungere o rimuovere nuovi lavoratori dovrebbe essere dinamico. Se vuoi assicurarti che i nuovi lavoratori acquisiscano compiti in Kakfa, dovrai impostare il numero della partizione al massimo dei lavoratori. Questo non è abbastanza elegante.

Quindi la linea di fondo - utilizzare RabbitMQ o altre code.

Detto tutto questo - Samza (di LinkedIn) utilizza Kafka come una sorta di streaming di coda di attività in base: Samza

+2

Potrebbe anche essere utile menzionare il fatto che l'esecuzione di offset rapidamente diventa complessa per gestire attività non riuscite che devono essere riprovate. – Ztyx

+2

"in Kafka per ottenere pienamente che si deve avere un solo consumatore e una partizione" non è corretto. L'ordine è garantito per ogni partizione in argomento in base alla chiave di partizione. Quindi, se l'ordine è importante, è necessario partizionare il valore su cui l'ordine è importante. Si tratta di garanzie di ordine più efficaci rispetto a rabbitmq, che può avere solo un consumatore per garantire l'ordine. –

+0

ma poi puoi avere un solo consumatore. che non è abbastanza buono –

4

Direi che questo dipende dalla scala. Quanti compiti prevedi in un'unità di tempo?

Quello che descrivi come obiettivo finale è fondamentalmente il funzionamento di Kafka per impostazione predefinita. Quando si producono messaggi, l'opzione predefinita (più usata) è quella di usare il partizionatore casuale, che sceglie le partizioni nel modo round robin, mantenendo le partizioni usate in modo uniforme (quindi è possibile evitare di specificare una partizione).
Lo scopo principale delle partizioni è quello di parallelizzare l'elaborazione dei messaggi, quindi è necessario utilizzarlo in questo modo.
Un'altra "cosa" comunemente utilizzata per cui le partizioni vengono utilizzate garantisce che determinati messaggi vengano consumati nello stesso ordine in cui vengono prodotti (quindi si specifica la chiave di partizionamento in modo tale che tutti i messaggi finiscano nella stessa partizione. utilizzando userId come chiave garantirebbe che tutti gli utenti vengano elaborati in questo modo).

+2

Grazie per la tua risposta Marko, forse possiamo andare fino in fondo con un esempio. Quindi diciamo che abbiamo 20 partizioni e 2 lavoratori e 100 nuovi posti di lavoro. Con round robin, i messaggi di lavoro vengono distribuiti a ogni partizione, quindi ogni utente riceve 10 partizioni, ovvero 50 lavori. Supponi che i 50 lavori di un consumatore impieghino 100 millisecondi (per tutti quelli combinati), ma i 50 lavori dell'altro consumatore richiedono 2 minuti. Il consumatore che ha finito presto sarà in grado di aiutare il consumatore sovraccarico? Kafka fa una sorta di ipotesi sulle pari difficoltà lavorative? – nephets

+1

Hey Marko, penso che la mia ultima domanda in quel commento sia arrivata al cuore del problema qui, se puoi aggiungere qualche dettaglio in più, allora accetterò sicuramente la tua risposta! – nephets

+0

Uno qualsiasi di quei 100 messaggi andrebbe a una partizione casuale e verrebbe preso da uno di quei due (cioè random) consumatori, quindi il secondo messaggio, quindi il terzo, ... quindi non è come ogni Consumatore otterrà un grosso di 50 messaggi, ovvero "si aiutano a vicenda". Ma perché ti limiti a 2 soli thread di consumo? Inoltre, si impegna l'offset solo dopo l'elaborazione di ciascun messaggio, per assicurarsi di non perdere alcun messaggio se l'elaborazione non ha esito positivo. –

1

Ci sono due ostacoli principali nel tentativo di usare Kafka come una coda di messaggi:

  1. come descritto in Ofer's answer, è possibile solo consumare una singola partizione da un singolo consumatore e l'ordine di elaborazione è garantito solo all'interno di una partizione. Quindi, se non è possibile distribuire equamente le attività tra le partizioni, questo potrebbe essere un problema

  2. per impostazione predefinita, è possibile solo accettare l'elaborazione di tutti i messaggi fino a un determinato punto (offset). A differenza delle code di messaggi tradizionali, non è possibile eseguire il riconoscimento selettivo e, in caso di errore, tentativi selettivi. Questo indirizzo può essere utilizzato utilizzando kmq, che aggiunge funzionalità di singoli utenti con l'aiuto di un argomento aggiuntivo (dichiarazione di non responsabilità: sono l'autore di kmq).

RabbitMQ è un'alternativa naturalmente, ma dà anche diversi (inferiori) prestazioni e la replicazione garanzie. In breve, i documenti RabbitMQ affermano che il broker is not partition tolerant. Vedi anche il nostro confronto delle code dei messaggi con la replica dei dati, mqperf.

Problemi correlati