Capisce i broker di messagi. Amparate a meccanica di messageria cù ActiveMQ è Kafka. Capitulu 3. Kafka

Continuazione di a traduzzione di un picculu libru:
Capisce i brokers di messagi
autore: Jakub Korab, editore: O'Reilly Media, Inc., data di pubblicazione: ghjugnu 2017, ISBN: 9781492049296.

Parte tradutta precedente: Capisce i brokers di messagi. Amparate a meccanica di messageria cù ActiveMQ è Kafka. Capitulu 1 Introduzione

CAPITOLU 3

Kafka

Kafka hè statu sviluppatu da LinkedIn per aggirari alcune di e limitazioni di i brokers tradiziunali di messagi è evità di avè da stallà parechji brokers di messagi per diverse interazzioni puntu à puntu, chì hè descritta in stu libru in "Scaling up and out" in a pagina 28. . Casi d'usu LinkedIn hà largamente s'appoghjanu nantu à l'ingerimentu unidirezionale di quantità assai grande di dati, cum'è clicchi di pagina è logs d'accessu, mentre chì permettenu ancu chì i dati sò usati da parechji sistemi senza impactà a produtividade di i pruduttori o altri cunsumatori. In fatti, u mutivu di Kafka esiste hè di ottene u tipu d'architettura di messageria chì u Universal Data Pipeline descrive.

In vista di questu scopu ultimu, altre esigenze sò naturalmente. Kafka deve:

  • Siate estremamente veloce
  • Fornite più larghezza di banda quandu travagliate cù i missaghji
  • Support Publisher-Abbonatu è mudelli Point-to-Point
  • Ùn rallentate micca cù l'aghjunghje i cunsumatori. Per esempiu, u rendimentu di a fila è di u tema in ActiveMQ si degrade cum'è u numeru di cunsumatori nantu à a destinazione cresce.
  • Esse scalable horizontalmente; se un broker chì persiste i missaghji pò fà solu à a velocità massima di u discu, allora hè sensu per andà oltre una sola istanza di broker per aumentà u rendiment.
  • Limite l'accessu à l'almacenamiento è a ricuperazione di i missaghji

Per ottene tuttu questu, Kafka hà aduttatu una architettura chì hà ridefinitu i roli è e rispunsabilità di i clienti è i brokers di messageria. U mudellu JMS hè assai orientatu à u broker, induve u broker hè rispunsevule per a distribuzione di messagi è i clienti solu anu da preoccupassi di mandà è riceve messagi. Kafka, invece, hè centratu in u cliente, cù u cliente chì piglia assai di e caratteristiche di un broker tradiziunale, cum'è una distribuzione ghjusta di messagi pertinenti à i cunsumatori, in cambiu di un broker estremamente veloce è scalabile. Per e persone chì anu travagliatu cù sistemi di messageria tradiziunali, u travagliu cù Kafka richiede un cambiamentu fundamentale di mente.
Questa direzzione di l'ingegneria hà purtatu à a creazione di una infrastruttura di messageria capace di aumentà u throughput da parechji ordini di grandezza cumparatu cù un broker convenzionale. Comu avemu vistu, questu approcciu vene cun cummerci, chì significa chì Kafka ùn hè micca adattatu per certi tipi di carichi di travagliu è software installatu.

Modellu di Destinazione Unificata

Per cumpiendu i requisiti descritti sopra, Kafka hà cumminatu publish-subscribe è messageria puntu à puntu sottu un tipu di destinazione - tema. Questu hè cunfusu à e persone chì anu travagliatu cù sistemi di messageria, induve a parolla "tema" si riferisce à un mecanismu di trasmissione da quale (da u tema) a lettura ùn hè durabile. I temi di Kafka deve esse cunsideratu un tipu di destinazione hibrida, cum'è definitu in l'intruduzioni à stu libru.

Per u restu di stu capitulu, salvu chì ùn dicemu esplicitamente altrimenti, u terminu "tema" si riferirà à un tema Kafka.

Per capiscenu cumplettamente cumu si cumportanu i temi è quali garanzii furniscenu, avemu bisognu di prima guardà cumu sò implementati in Kafka.
Ogni tema in Kafka hà u so propiu log.
I pruduttori chì mandanu messagi à Kafka scrivenu à questu logu, è i cunsumatori leghjenu da u logu usendu punters chì avanzanu constantemente. Periòdicamente, Kafka sguassate i parti più antichi di u logu, sì i missaghji in quelli parti sò stati letti o micca. Una parte cintrali di u disignu di Kafka hè chì u broker ùn importa micca se i missaghji sò letti o micca - questu hè a rispunsabilità di u cliente.

I termini "log" è "pointer" ùn si prisentanu micca Kafka documentazione. Questi termini ben cunnisciuti sò usati quì per aiutà à capiscenu.

Stu mudellu hè cumplettamente sfarente da ActiveMQ, induve i missaghji da tutte e fila sò guardati in u stessu logu, è u broker marca i missaghji cum'è sguassati dopu chì sò stati letti.
Andemu avà un pocu più in fondu è fighjemu u logu di u tema in più dettagliu.
U log Kafka hè custituitu da parechje partizioni (Figura 3-1). Kafka guarantisci un ordine strettu in ogni partizione. Questu significa chì i missaghji scritti à a partizione in un certu ordine seranu leghje in u stessu ordine. Ogni partizione hè implementata cum'è un schedariu di log rolling chì cuntene un sottumessu (subset) di tutti i missaghji mandati à u tema da i so pruduttori. U tema creatu cuntene, per difettu, una partizione. L'idea di partizioni hè l'idea centrale di Kafka per a scala horizontale.

Capisce i broker di messagi. Amparate a meccanica di messageria cù ActiveMQ è Kafka. Capitulu 3. Kafka
Figura 3-1. Spartizioni Kafka

Quandu un pruduttore manda un missaghju à un tema di Kafka, decide à quale partizione mandà u messagiu. Fighjeremu questu in più detail dopu.

Lettura di missaghji

U cliente chì vole leghje i missaghji gestisce un puntatore chjamatu chjamatu gruppu di cunsumatori, chì punta à offset missaghji in a particione. Un offset hè una pusizione incrementale chì principia da 0 à l'iniziu di una partizione. Stu gruppu di cunsumatori, riferitu in l'API via u group_id definitu da l'utilizatori, currisponde à un consumatore o sistema logicu.

A maiò parte di i sistemi di messageria leghjenu dati da u destinazione utilizendu parechje istanze è fili per processà i missaghji in parallelu. Cusì, ci saranu generalmente parechje istanze di cunsumatori chì sparte u stessu gruppu di cunsumatori.

U prublema di a lettura pò esse rapprisintatu cusì:

  • U tema hà parechje partizioni
  • Diversi gruppi di cunsumatori ponu utilizà un tema à u stessu tempu
  • Un gruppu di cunsumatori pò avè parechje istanze separati

Questu hè un prublema assai-à-molti micca trivial. Per capisce cumu Kafka gestisce e relazioni trà gruppi di cunsumatori, istanze di cunsumatori è partizioni, fighjemu una seria di scenarii di lettura progressivamente più cumplessi.

Cunsumatori è gruppi di cunsumatori

Pigliemu cum'è puntu di partenza un tema cù una partizione (Figura 3-2).

Capisce i broker di messagi. Amparate a meccanica di messageria cù ActiveMQ è Kafka. Capitulu 3. Kafka
Figura 3-2. U cunsumadore leghje da a partizione

Quandu una istanza di cunsumu cunnetta cù u so propiu group_id à questu tema, hè assignatu una partizione di lettura è un offset in quella partizione. A pusizione di questu offset hè cunfigurata in u cliente cum'è un punteru à a pusizione più recente (messagiu più recente) o a pusizione più antica (messagiu più anticu). U cunsumadore dumanda (polls) missaghji da u tema, chì li face esse leghje sequentially da u log.
A pusizione di offset hè rigularmente rimessa à Kafka è guardata cum'è messagi in un tema internu _consumer_offsets. I missaghji di lettura ùn sò micca ancu sguassati, à u cuntrariu di un broker regulare, è u cliente pò ritruvà l'offset per riprocessà i missaghji digià vistu.

Quandu un secondu consumatore logicu cunnetta utilizendu un differente group_id, gestisce un secondu puntatore chì hè indipendente da u primu (Figura 3-3). Cusì, un tema di Kafka agisce cum'è una fila induve ci hè un cunsumadore è cum'è un tema di pubblicazione-subscribe (pub-sub) normale chì parechji cunsumatori abbonanu, cù u benefiziu aghjuntu chì tutti i missaghji sò almacenati è ponu esse processati parechje volte.

Capisce i broker di messagi. Amparate a meccanica di messageria cù ActiveMQ è Kafka. Capitulu 3. Kafka
Figura 3-3. Dui cunsumatori in diversi gruppi di cunsumatori leghjenu da a listessa partizione

I cunsumatori in un gruppu di cunsumatori

Quandu una istanza di cunsumadore leghje e dati da una partizione, hà un cuntrollu tutale di u puntatore è processa i missaghji cum'è descrittu in a sezione precedente.
Se parechji casi di cunsumatori sò stati cunnessi cù u stessu group_id à un tema cù una partizione, allora l'istanza chì hà cunnessu l'ultimu serà datu u cuntrollu di u puntatore è da quellu mumentu riceverà tutti i missaghji (Figura 3-4).

Capisce i broker di messagi. Amparate a meccanica di messageria cù ActiveMQ è Kafka. Capitulu 3. Kafka
Figura 3-4. Dui cunsumatori in u stessu gruppu di cunsumatori leghjenu da a listessa partizione

Stu modu di trasfurmazioni, in quale u numeru di casi di cunsumatori supera u numeru di partizioni, pò esse pensatu cum'è una spezia di cunsumadore esclusivu. Questu pò esse utile s'ellu avete bisognu di "attivu-passivu" (o "caldo-caldo") clustering di i vostri istanze di u cunsumadore, anche se eseguisce parechji cunsumatori in parallelu ("attivu-attivu" o "caldo-caldo") hè assai più tipicu cà i cunsumatori In standby.

Stu cumpurtamentu di distribuzione di missaghju descrittu sopra pò esse surprisante paragunatu à cumu si cumporta una fila JMS normale. In questu mudellu, i missaghji mandati à a fila seranu distribuiti uniformemente trà i dui cunsumatori.

A maiò spessu, quandu creamu parechje istanze di cunsumatori, facemu questu per processà i missaghji in parallelu, o per aumentà a vitezza di lettura, o per aumentà a stabilità di u prucessu di lettura. Siccomu solu una istanza di u cunsumadore pò leghje e dati da una partizione à u mumentu, cumu si ottene questu in Kafka?

Una manera di fà questu hè di utilizà una sola istanza di cunsumu per leghje tutti i missaghji è passanu à a piscina di fili. Mentre chì stu approcciu aumenta a produzzione di trasfurmazioni, aumenta a cumplessità di a logica di u cunsumadore è ùn face nunda per aumentà a robustezza di u sistema di lettura. Se una copia di u cunsumadore scende per una mancanza di energia o un avvenimentu simili, a sottrazione si ferma.

U modu canonicu per risolve stu prublema in Kafka hè di utilizà bОpiù partizioni.

Spartizione

E partizioni sò u mecanismu principale per parallelizà a lettura è a scala di un tema oltre a larghezza di banda di una sola istanza di broker. Per capisce megliu questu, cunsideremu una situazione induve ci hè un tema cù duie partizioni è un cunsumadore abbonatu à questu tema (Figura 3-5).

Capisce i broker di messagi. Amparate a meccanica di messageria cù ActiveMQ è Kafka. Capitulu 3. Kafka
Figura 3-5. Un cunsumadore leghje da parechje partizioni

In questu scenariu, u cunsumadore hè datu u cuntrollu di i puntatori chì currispondenu à u so group_id in e duie partizioni è principia à leghje i missaghji da e duie partizioni.
Quandu un cunsumadore supplementu per u stessu group_id hè aghjuntu à questu tema, Kafka rilocate una di e partizioni da u primu à u sicondu cunsumadore. Dopu quì, ogni istanza di u cunsumadore leghje da una partizione di u tema (Figura 3-6).

Per assicurà chì i missaghji sò trattati in parallelu in 20 fili, avete bisognu di almenu 20 partizioni. S'ellu ci hè menu partizioni, vi sarà lasciatu cù i cunsumatori chì ùn anu nunda di travaglià, cum'è discrittu prima in a discussione di i cunsumatori esclusivi.

Capisce i broker di messagi. Amparate a meccanica di messageria cù ActiveMQ è Kafka. Capitulu 3. Kafka
Figura 3-6. Dui cunsumatori in u stessu gruppu di cunsumatori leghjenu da diverse partizioni

Stu schema reduce assai a cumplessità di u broker Kafka cumparatu cù a distribuzione di missaghju necessaria per mantene a fila JMS. Quì ùn avete micca bisognu di preoccupari di i seguenti punti:

  • Quale cunsumadore deve riceve u missaghju prossimu, basatu annantu à l'allocazione round-robin, a capacità attuale di i buffer di prefetch, o i missaghji precedenti (cum'è per i gruppi di messagi JMS).
  • Chì missaghji sò mandati à quale cunsumatori è s'ellu deve esse rimandatu in casu di fallimentu.

Tuttu u broker Kafka hà da fà hè di passà i missaghji in sequenza à u cunsumadore quandu l'ultimu li dumanda.

In ogni casu, i requisiti per a parallelisazione di a correzione di prova è di rinvià i missaghji falluti ùn si ne vanu - a rispunsabilità per elli passa solu da u broker à u cliente. Questu significa chì deve esse cunsideratu in u vostru codice.

Mandatu missaghji

Hè a rispunsabilità di u pruduttore di quellu missaghju di decide à quale partizione mandà un missaghju. Per capisce u miccanisimu da quale questu hè fattu, prima avemu bisognu di cunsiderà ciò chì esattamente avemu da mandà.

Mentre chì in JMS usemu una struttura di missaghju cù metadati (intestazione è pruprietà) è un corpu chì cuntene u payload (payload), in Kafka u messagiu hè coppia "key-value". U messagiu payload hè mandatu cum'è valore. A chjave, invece, hè principarmenti utilizata per a partizione è deve cuntene chjave specifica di a logica cummercialeper mette messagi cunnessi in a listessa partizione.

In u Capitulu 2, avemu discututu u scenariu di scumessa in linea induve l'avvenimenti cunnessi anu da esse processati in ordine da un solu cunsumadore:

  1. U contu d'utilizatore hè cunfiguratu.
  2. U soldi hè creditu à u contu.
  3. Una scumessa hè fatta chì ritira soldi da u contu.

Se ogni avvenimentu hè un missaghju publicatu à un tema, allora a chjave naturale seria l'ID di u contu.
Quandu un missaghju hè mandatu cù l'API Kafka Producer, hè passatu à una funzione di partizione chì, datu u missaghju è u statu attuale di u cluster Kafka, torna l'ID di a partizione à quale u messagiu deve esse mandatu. Questa funzione hè implementata in Java per mezu di l'interfaccia Partitioner.

Questa interfaccia s'assumiglia cusì:

interface Partitioner {
    int partition(String topic,
        Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster);
}

L'implementazione di Partitioner usa l'algoritmu di hashing per u scopu generale predeterminatu nantu à a chjave per determinà a partizione, o round-robin se ùn ci hè micca una chjave specifica. Stu valore predeterminatu funziona bè in a maiò parte di i casi. Tuttavia, in u futuru vi vulete scrive u vostru propiu.

Scrivite a vostra propria strategia di partizionamentu

Fighjemu un esempiu induve vulete mandà metadata cù a carica di missaghju. A carica in u nostru esempiu hè una struzzione per fà un accontu à u contu di ghjocu. Una struzzione hè qualcosa chì vulemu esse guarantiti chì ùn sia micca mudificatu nantu à a trasmissione è vulemu esse sicuru chì solu un sistema upstream di fiducia pò inizià quella struzzione. In questu casu, i sistemi di mandatu è di ricezione accunsenu à l'usu di una firma per autentificà u messagiu.
In JMS normale, simpricimenti definisce una pruprietà "firma di missaghju" è aghjunghje à u messagiu. Tuttavia, Kafka ùn ci furnisce micca un mecanismu per passà metadata, solu una chjave è un valore.

Siccomu u valore hè una carica di trasferimentu bancariu chì a so integrità vulemu priservà, ùn avemu micca scelta ma di definisce a struttura di dati da utilizà in a chjave. Assumindu chì avemu bisognu di un ID di contu per u particionamentu, postu chì tutti i missaghji ligati à un contu deve esse processatu in ordine, avemu da vene cù a seguente struttura JSON:

{
  "signature": "541661622185851c248b41bf0cea7ad0",
  "accountId": "10007865234"
}

Perchè u valore di a firma varierà secondu a carica utile, a strategia di hashing predeterminata di l'interfaccia di Partitioner ùn agruparà micca in modu affidabile i missaghji in relazione. Dunque, avemu bisognu di scrive a nostra propria strategia chì analizà sta chjave è particionà u valore accountId.

Kafka include checksums per detectà a corruzzione di i missaghji in a tenda è hà un inseme cumpletu di funzioni di sicurità. Ancu cusì, i bisogni specifichi di l'industria, cum'è quellu sopra, appariscenu qualchì volta.

A strategia di spartizione di l'utilizatori deve assicurà chì tutti i missaghji cunnessi finiscinu in a listessa partizione. Mentre chì questu pare simplice, u requisitu pò esse cumplicatu da l'impurtanza di l'urdinamentu di messagi cunnessi è quantu hè fissatu u numeru di partizioni in un tema.

U numaru di partizioni in un tema pò cambià cù u tempu, cum'è ponu esse aghjuntu se u trafficu supera l'aspettattivi iniziali. Cusì, i chjavi di missaghju ponu esse assuciati cù a partizione chì sò stati urigginariamenti mandati, chì implicanu un pezzu di statu per esse spartutu trà l'istanze di pruduttori.

Un altru fattore da cunsiderà hè a distribuzione uniforme di missaghji in partizioni. Di genere, i chjavi ùn sò micca distribuiti uniformemente in i missaghji, è e funzioni di hash ùn guarantisci micca una distribuzione ghjusta di missaghji per un picculu gruppu di chjave.
Hè impurtante à nutà chì, però, sceglite di sparte i missaghji, u separatore stessu pò esse riutilizzatu.

Cunsiderate l'esigenza di riplicà e dati trà i cluster Kafka in diverse lochi geografichi. Per questu scopu, Kafka vene cun un strumentu di linea di cumanda chjamatu MirrorMaker, chì hè utilizatu per leghje i missaghji da un cluster è trasfiriri à un altru.

MirrorMaker deve capisce i chjavi di u tema replicatu per mantene l'ordine relativo trà i missaghji quandu si riplica trà i clusters, postu chì u numeru di partizioni per quellu tema pò esse micca u listessu in dui clusters.

E strategie di partizionamentu persunalizati sò relativamente rari, postu chì l'hashing predefinitu o round robin funziona bè in a maiò parte di i scenari. Tuttavia, se avete bisognu di garanzie d'ordine forti o avete bisognu di estrazione di metadati da carichi utili, allora u partizionamentu hè qualcosa chì duvete guardà più attente.

I benefici di scalabilità è di prestazione di Kafka venenu da trasfurmà alcune di e rispunsabilità di u broker tradiziunale à u cliente. In questu casu, una decisione hè presa per distribuisce messagi potenzialmente ligati trà parechji cunsumatori chì travaglianu in parallelu.

I brokers JMS anu ancu bisognu di trattà cun tali esigenze. Curiosamente, u mecanismu per mandà messagi cunnessi à u stessu cunsumadore, implementatu per mezu di Gruppi di Messaggi JMS (una variazione di a strategia di bilanciamentu di carica appiccicosa (SLB)), richiede ancu chì u mittente marcà i missaghji cum'è rilativi. In u casu di JMS, u broker hè rispunsevuli di mandà stu gruppu di messagi cunnessi à un cunsumadore di parechji, è di trasfiriri a pruprietà di u gruppu se u cunsumadore casca.

Accordi di pruduttori

A particione ùn hè micca solu ciò chì deve esse cunsideratu quandu invià missaghji. Fighjemu un ochju à i metudi send() di a classa Producer in l'API Java:

Future < RecordMetadata > send(ProducerRecord < K, V > record);
Future < RecordMetadata > send(ProducerRecord < K, V > record, Callback callback);

Si deve esse nutatu subitu chì i dui metudi torna Future, chì indica chì l'operazione di mandà ùn hè micca realizatu immediatamente. U risultatu hè chì un missaghju (ProducerRecord) hè scrittu à u buffer di mandatu per ogni partizione attiva è mandatu à u broker cum'è un filu di fondo in a biblioteca di u cliente Kafka. Mentre chì questu rende e cose incredibilmente veloce, significa chì una applicazione senza sperienza pò perde i missaghji se u so prucessu hè firmatu.

Comu sempre, ci hè un modu per fà l'operazione di mandatu più affidabile à u costu di u rendiment. A dimensione di stu buffer pò esse stabilitu à 0, è u filu di l'applicazione di l'inviu serà obligatu à aspittà finu à chì u trasferimentu di missaghju à u broker hè cumpletu, cusì:

RecordMetadata metadata = producer.send(record).get();

Più nantu à leghje i missaghji

A lettura di i missaghji hà cumplessità supplementari chì deve esse speculati. A cuntrariu di l'API JMS, chì pò eseguisce un listener di messagi in risposta à un messagiu, u Franchising Kafka solu sonda. Fighjemu un ochju più vicinu à u metudu sondaghju ()usatu per questu scopu:

ConsumerRecords < K, V > poll(long timeout);

U valore di ritornu di u metudu hè una struttura di cuntainer chì cuntene parechje oggetti record di cunsumatori da diverse partizioni potenziali. record di cunsumatori hè ellu stessu un oggettu di titulari per una coppia chjave-valore cù metadata assuciata, cum'è a partizione da quale hè derivata.

Comu discutitu in u Capitulu 2, duvemu tene in mente ciò chì succede à i missaghji dopu chì sò stati processati cù successu o senza successu, per esempiu, se u cliente ùn hè micca capaci di processà u messagiu o s'ellu abortisce. In JMS, questu hè statu trattatu attraversu un modu di ricunniscenza. U broker sia sguassate u missaghju trattatu cù successu, o rinvià u missaghju crudu o falsu (assumendu chì e transacciones sò state aduprate).
Kafka travaglia assai diversamente. I missaghji ùn sò micca sguassati in u broker dopu a correzzione, è ciò chì succede in u fallimentu hè a rispunsabilità di u codice di correzione stessu.

Comu avemu dettu, u gruppu di cunsumatori hè assuciatu cù l'offset in u logu. A pusizione di logu assuciata cù questu offset currisponde à u prossimu missaghju chì deve esse emessu in risposta sondaghju (). U puntu in u tempu quandu questu offset aumenta hè decisivu per a lettura.

Riturnendu à u mudellu di lettura discutitu prima, u prucessu di missaghju si compone di trè fasi:

  1. Ritruvà un missaghju per leghje.
  2. Prucessa u missaghju.
  3. Cunfirmà u missaghju.

U cunsumadore Kafka vene cun una opzione di cunfigurazione attivà.auto.commit. Questu hè un paràmetru predeterminatu spessu usatu, cum'è cumunu cù i paràmetri chì cuntenenu a parolla "auto".

Prima di Kafka 0.10, un cliente chì usa sta opzione mandava l'offset di l'ultimu messagiu leghje nantu à a prossima chjama sondaghju () dopu a trasfurmazioni. Questu significava chì ogni messagiu chì era digià statu purtatu puderia esse riprocessatu se u cliente l'avia digià processatu, ma hè statu distruttu inaspettatamente prima di chjamà. sondaghju (). Perchè u broker ùn mantene nisun statu nantu à quante volte un missaghju hè statu lettu, u prossimu cunsumadore chì ricuperà quellu missaghju ùn saperà nunda di male. Stu cumpurtamentu era pseudo-transazionale. L'offset hè statu fattu solu se u missaghju hè statu processatu bè, ma se u cliente hà abortutu, u broker mandava u stessu missaghju à un altru cliente. Stu cumpurtamentu era coherente cù a guaranzia di spedizione di messagiu "almenu una volta".

In Kafka 0.10, u codice di u cliente hè statu cambiatu in modu chì l'impegnu hè attivatu periodicamente da a biblioteca di u cliente, cum'è cunfiguratu. auto.commit.interval.ms. Stu cumpurtamentu hè in un locu trà i modi JMS AUTO_ACKNOWLEDGE è DUPS_OK_ACKNOWLEDGE. Quandu s'utilice l'autocommit, i missaghji ponu esse impegnati, indipendendu s'ellu sò stati processati veramente - questu puderia accade in u casu di un cunsumadore lento. Se un cunsumadore avortava, i missaghji seranu purtati da u prossimu cunsumadore, cumincendu da a pusizione impegnata, chì puderia risultà in un missaghju miss. In questu casu, Kafka ùn hà micca persu i missaghji, u codice di lettura ùn hà micca processatu.

Stu modu hà a listessa prumessa cum'è in a versione 0.9: i missaghji ponu esse processati, ma s'ellu ùn falla, l'offset ùn pò micca esse impegnatu, putenzialmente pruvucannu a consegna per duppià. U più messagi caccià quandu eseguite sondaghju (), u più stu prublema.

Cum'è discutitu in "Lettura di i missaghji da una fila" in a pagina 21, ùn ci hè micca una consegna una volta di un messagiu in un sistema di messageria quandu i modi di fallimentu sò presi in contu.

In Kafka, ci sò duie manere di commit (commit) un offset (offset): automaticamente è manualmente. In i dui casi, i missaghji ponu esse trattati parechje volte se u missaghju hè statu processatu ma hà fiascatu prima di l'impegnu. Pudete ancu sceglie micca di processà u missaghju in tuttu s'ellu l'impegnu hè accadutu in u sfondate è u vostru codice hè statu cumpletu prima di pudè esse processatu (forse in Kafka 0.9 è prima).

Pudete cuntrullà u prucessu di cummissione di offset manuale in l'API di cunsumu Kafka per stabilisce u paràmetru attivà.auto.commit à false è chjamà esplicitamente unu di i metudi seguenti:

void commitSync();
void commitAsync();

Sè vo vulete processà u missaghju "almenu una volta", vi tocca à cummette u offset manually cù commitSync()da esecutà stu cumanda subitu dopu à trasfurmà i missaghji.

Questi metudi ùn permettenu micca di ricunnosce i missaghji prima di esse processati, ma ùn facenu nunda per eliminà i ritardi potenziali di trasfurmazioni mentre dà l'apparenza di esse transazzione. Ùn ci sò micca transazzioni in Kafka. U cliente ùn hà micca a capacità di fà i seguenti:

  • Ritorna automaticamente un missaghju falsificatu. I cunsumatori stessi anu da trattà l'eccezzioni derivanti da carichi problematici è interruzioni di backend, postu chì ùn ponu micca affidate à u broker per rinvià i missaghji.
  • Mandate missaghji à parechji temi in una operazione atomica. Comu vedemu prestu, u cuntrollu di e diverse temi è partizioni ponu reside in diverse macchine in u cluster Kafka chì ùn coordinanu micca e transazzione quandu sò mandati. À u mumentu di sta scrittura, un pocu di travagliu hè statu fattu per fà questu pussibule cù u KIP-98.
  • Associate a lettura di un missaghju da un tema cù l'inviu di un altru missaghju à un altru tema. In novu, l'architettura di Kafka dipende da parechje macchine indipendenti chì funzionanu cum'è un autobus è ùn hè micca tentativu di ammuccià questu. Per esempiu, ùn ci sò micca cumpunenti API chì vi permettenu di ligà cunsumadore и Produttore in una transazzione. In JMS, questu hè furnitu da l'ughjettu Corsica Madnessda quale sò creati I pruduttori di messagi и MessageConsumers.

Se ùn pudemu micca cunfidassi di e transazzione, cumu pudemu furnisce semantica più vicinu à quelli furniti da i sistemi di messageria tradiziunali ?

Se ci hè una pussibilità chì l'offset di u cunsumadore pò aumentà prima chì u messagiu hè statu processatu, cum'è durante un crash di u cunsumadore, allora u cunsumadore ùn hà micca manera di sapè se u so gruppu di cunsumatori hà mancatu u messagiu quandu hè assignatu una partizione. Dunque, una strategia hè di rinvià l'offset à a pusizione precedente. L'API di cunsumatori Kafka furnisce i seguenti metudi per questu:

void seek(TopicPartition partition, long offset);
void seekToBeginning(Collection < TopicPartition > partitions);

Metu cerca () pò esse usatu cù u metudu
offsetsForTimes (Map timestampsToSearch) per retrocede à un statu in un puntu specificu in u passatu.

Implicitly, usendu stu approcciu significa chì hè assai prubabile chì certi missaghji chì sò stati processati prima seranu letti è processati di novu. Per evitari questu, pudemu usà a lettura idempotente, cum'è descritta in u Capitulu 4, per guardà i missaghji visti prima è eliminà i duplicati.

In alternativa, u vostru codice di u cunsumu pò esse guardatu simplice, finu à chì a perdita di missaghju o a duplicazione hè accettata. Quandu avemu cunsideratu i casi d'usu per quale Kafka hè cumunimenti utilizatu, cum'è a gestione di l'avvenimenti di log, metriche, cliccà traccia, etc., avemu capitu chì a perdita di messagi individuali hè improbabile di avè un impattu significativu in l'applicazioni circundante. In tali casi, i valori predeterminati sò perfettamente accettabili. Per d 'altra banda, se a vostra applicazione hà bisognu di mandà pagamenti, duvete piglià cura di ogni missaghju individuale. Tuttu vene à u cuntestu.

L'osservazioni persunale mostranu chì quandu l'intensità di i missaghji aumenta, u valore di ogni missaghju individuale diminuisce. I missaghji grandi tendenu à esse preziosi quandu visti in una forma aggregata.

Alta Disponibilità

L'approcciu di Kafka à l'alta dispunibilità hè assai sfarente da l'approcciu di ActiveMQ. Kafka hè cuncepitu intornu à clusters scale-out induve tutte l'istanze di broker ricevenu è distribuiscenu messagi à u stessu tempu.

Un cluster Kafka hè custituitu da parechje istanze di broker in esecuzione in diversi servitori. Kafka hè statu cuncepitu per eseguisce nantu à hardware standalone ordinariu, induve ogni nodu hà u so propiu almacenamentu dedicatu. L'usu di l'almacenamiento attaccatu à a rete (SAN) ùn hè micca cunsigliatu perchè parechji nodi di compute ponu cumpete per u tempu.Ыe intervalli di almacenamiento è creanu cunflitti.

Kafka hè sempre nantu sistema. Parechji grandi utilizatori Kafka ùn anu mai chjusu i so clusters è u software sempre aghjurnà cù un riavviu sequenziale. Questu hè ottenutu da guarantisci a cumpatibilità cù a versione precedente per i missaghji è l'interazzione trà i brokers.

Brokers cunnessi à un cluster di servitori ZooKeeper, chì agisce cum'è un registru di dati di cunfigurazione è hè utilizatu per coordinà i roli di ogni broker. ZooKeeper stessu hè un sistema distribuitu chì furnisce una alta dispunibilità attraversu a replicazione di l'infurmazioni stabilendu quorum.

In u casu di basa, un tema hè creatu in un cluster Kafka cù e seguenti proprietà:

  • U numaru di partizioni. Comu discutitu prima, u valore esattu utilizatu quì dipende da u livellu desideratu di lettura parallela.
  • U fattore di replicazione (fattore) determina quante istanze di broker in u cluster deve cuntene logs per questa partizione.

Utilizendu ZooKeepers per a coordinazione, Kafka prova di distribuisce equamente novi partizioni trà i brokers in u cluster. Questu hè fattu da una sola istanza chì agisce cum'è Controller.

In tempu di runtime per ogni partizione tematica Cuntrollore assignà roli à un broker capu (leader, maestru, presentatore) è seguitori (seguitori, schiavi, subordinati). U broker, cum'è u capu di sta partizione, hè rispunsevule per riceve tutti i missaghji mandati da i pruduttori è distribuisce i missaghji à i cunsumatori. Quandu i missaghji sò mandati à una partizione tematica, sò riplicati à tutti i nodi di broker chì facenu cum'è seguitori per quella partizione. Ogni node chì cuntene logs per una partizione hè chjamatu replica. Un broker pò agisce cum'è un capu per certi partizioni è cum'è seguitore per altri.

Un seguitore chì cuntene tutti i missaghji tenuti da u capu hè chjamatu replica sincronizata (una replica chì hè in un statu sincronizatu, replica in-sync). Se un broker chì agisce cum'è un capu per una partizione cade, qualsiasi broker chì hè aghjurnatu o sincronizatu per quella partizione pò piglià u rolu di capu. Hè un disignu incredibbilmente sustenibile.

A parte di a cunfigurazione di u pruduttore hè u paràmetru acchi, chì determina quante rèpliche anu da ricunnosce (ricunnosce) a ricezione di un messagiu prima chì u filu di l'applicazione cuntinueghja à mandà: 0, 1, o tutti. Se pusatu à tuttu, dopu quandu un missaghju hè ricevutu, u capu mandarà una cunferma torna à u pruduttori appena riceve cunfirmazioni (ricunniscenza) di u record da parechji spunti (cumpresu ellu stessu) definitu da u tema. min.insync.replicas (default 1). Se u messagiu ùn pò micca esse replicatu bè, allora u pruduttore lancerà una eccezzioni di l'applicazione (Not EnoughReplicas o Not EnoughReplicasAfterAppend).

Una cunfigurazione tipica crea un tema cù un fattore di replicazione di 3 (1 capu, 2 seguitori per partizione) è u paràmetru min.insync.replicas hè stabilitu à 2. In questu casu, u cluster permetterà à unu di i brokers chì gestiscenu a partizione di u tema per falà senza affettà l'applicazioni cliente.

Questu ci riporta à u scambiu digià familiare trà prestazioni è affidabilità. A replicazione si trova à a spesa di u tempu d'attesa supplementu per cunferma (ricunniscenza) da i seguitori. Ancu s'ellu, perchè corre in parallelu, a replicazione à almenu trè nodi hà u listessu rendimentu cum'è dui (ignorendu l'aumentu di l'usu di a larghezza di banda di a rete).

Utilizendu stu schema di replicazione, Kafka evita intelligentemente a necessità di scrive fisicamente ogni messagiu à u discu cù l'operazione. sync(). Ogni missaghju mandatu da u pruduttore serà scrittu à u logu di partizione, ma cum'è discutitu in u Capitulu 2, scrive à un schedariu hè inizialmente fattu in u buffer di u sistema upirativu. Se stu missaghju hè replicatu à un altru casu Kafka è hè in a so memoria, a perdita di u capu ùn significa micca chì u missaghju stessu hè statu persu - pò esse pigliatu da una replica sincronizata.
Rifiuta di fà l'operazione sync() significheghja chì Kafka pò riceve i missaghji più veloce chì pò scrive in memoria. À u cuntrariu, u più longu pudete evità di lavà a memoria à u discu, u megliu. Per quessa, ùn hè micca pocu cumu per i brokers Kafka per esse attribuiti 64 GB o più di memoria. Questu usu di a memoria significa chì una sola istanza Kafka pò esse facilmente eseguita à una velocità parechje millaie di volte più veloce di un broker di messagiu tradiziunale.

Kafka pò ancu esse cunfiguratu per applicà l'operazione sync() à i pacchetti di missaghju. Siccomu tuttu in Kafka hè orientatu à u pacchettu, in realtà funziona abbastanza bè per parechji casi d'usu è hè un strumentu utile per l'utilizatori chì necessitanu garanzii assai forti. A maiò parte di u funziunamentu puru di Kafka vene da i missaghji chì sò mandati à u broker cum'è pacchetti è chì sti missaghji sò letti da u broker in blocchi sequenziali cù copia zero operazioni (operazioni durante i quali u compitu di cupià dati da una zona di memoria à l'altru ùn hè micca realizatu). L'ultime hè un grande rendimentu è guadagnà risorse è hè pussibule solu per l'usu di una struttura di dati di log sottostanti chì definisce u schema di partizione.

Un rendimentu assai megliu hè pussibule in un cluster Kafka cà cù un solu broker Kafka, perchè e partizioni tematiche ponu scala in parechje macchine separate.

Risultati

In questu capitulu, avemu vistu cumu l'architettura Kafka reimagina a relazione trà i clienti è i brokers per furnisce una pipeline di messageria incredibilmente robusta, cù un throughput parechje volte più grande di quellu di un broker di messageria convenzionale. Avemu discututu a funziunalità chì usa per ottene questu è hà fighjatu brevemente l'architettura di l'applicazioni chì furnisce sta funziunalità. In u prossimu capitulu, andemu à fighjulà i prublemi cumuni chì l'applicazioni basate in messageria anu bisognu di risolve è di discussione di strategie per trattà cun elli. Finiremu u capitulu spieghendu cumu parlà di e tecnulugia di messageria in generale per pudè valutà a so adattabilità per i vostri casi d'usu.

Parte tradutta precedente: Capisce i broker di messagi. Amparate a meccanica di messageria cù ActiveMQ è Kafka. Capitulu 1

Traduzzione fatta: tele.gg/middle_java

Per esse continuatu ...

Solu l'utilizatori registrati ponu participà à l'indagine. Firmà lu, per piacè.

Hè Kafka utilizatu in a vostra urganizazione?

  • chì

  • No

  • Usatu prima, avà micca

  • Avemu pensa à aduprà

38 utilizatori anu vutatu. 8 utilizatori si sò astenuti.

Source: www.habr.com

Add a comment