Sõnumivahendaja mõistmine. Sõnumite saatmise mehaanika õppimine ActiveMQ ja Kafka abil. 3. peatükk. Kafka

Väikese raamatu tõlkimise jätk:
Sõnumimaaklerite mõistmine
autor: Jakub Korab, väljaandja: O'Reilly Media, Inc., avaldamise kuupäev: juuni 2017, ISBN: 9781492049296.

Eelmine tõlgitud osa: Sõnumivahendaja mõistmine. Sõnumite saatmise mehaanika õppimine ActiveMQ ja Kafka abil. 1. peatükk Sissejuhatus

3. PEATÜKK

Kafka

Kafka töötati välja LinkedInis, et ületada mõningaid traditsiooniliste sõnumivahendajate piiranguid ja vältida mitme sõnumivahendaja seadistamist erinevate punktidevaheliste interaktsioonide jaoks, mida on kirjeldatud selle raamatu jaotises "Suurendamine ja vähendamine" lk 28. Kasutusjuhtumid LinkedIn on suures osas tuginenud väga suurte andmemahtude, näiteks lehtede klõpsude ja juurdepääsulogide ühesuunalisele sissevõtmisele, võimaldades samal ajal neid andmeid kasutada mitmel süsteemil, ilma et see mõjutaks tootjate või teiste tarbijate tootlikkust. Tegelikult on Kafka olemasolu põhjus selles, et saada selline sõnumsidearhitektuur, mida Universal Data Pipeline kirjeldab.

Seda lõppeesmärki arvestades tekkisid loomulikult muud nõuded. Kafka peaks:

  • Olge äärmiselt kiire
  • Pakkuge sõnumitega töötamisel rohkem ribalaiust
  • Toetage väljaandja-abonendi ja punkt-punkti mudeleid
  • Ärge aeglustage tarbijate lisamisega. Näiteks nii järjekorra kui ka teema jõudlus ActiveMQ-s halveneb, kui sihtkoha tarbijate arv kasvab.
  • olema horisontaalselt skaleeritav; kui üks vahendaja, kes edastab sõnumeid, saab seda teha ainult maksimaalse kettakiirusega, on jõudluse suurendamiseks mõttekas minna kaugemale ühest vahendaja eksemplarist
  • Piirake juurdepääsu sõnumite salvestamisele ja uuesti allalaadimisele

Kõige selle saavutamiseks võttis Kafka kasutusele arhitektuuri, mis määratles uuesti klientide ja sõnumite vahendajate rollid ja kohustused. JMS-mudel on väga maaklerikeskne, kus vahendaja vastutab sõnumite levitamise eest ning kliendid peavad muretsema vaid sõnumite saatmise ja vastuvõtmise pärast. Kafka seevastu on kliendikeskne, kusjuures klient võtab vastu palju traditsioonilise maakleri omadusi, näiteks asjakohaste sõnumite õiglane jagamine tarbijatele, vastutasuks ülikiire ja skaleeritava maakleri eest. Inimeste jaoks, kes on töötanud traditsiooniliste sõnumisüsteemidega, nõuab Kafkaga töötamine põhimõttelist meelemuutust.
See insenerisuund on viinud sõnumside infrastruktuuri loomiseni, mis on võimeline suurendama läbilaskevõimet mitme suurusjärgu võrra võrreldes tavapärase maakleriga. Nagu näeme, kaasneb selle lähenemisviisiga kompromissid, mis tähendab, et Kafka ei sobi teatud tüüpi töökoormuse ja installitud tarkvara jaoks.

Ühtne sihtkoha mudel

Ülalkirjeldatud nõuete täitmiseks on Kafka kombineerinud avaldamise-tellimise ja punktist-punkti sõnumite saatmise ühte tüüpi sihtkohtadesse. teema. See tekitab segadust inimestes, kes on töötanud sõnumsidesüsteemidega, kus sõna "teema" viitab edastusmehhanismile, millest (teemast lähtuvalt) lugemine on kestev. Kafka teemasid tuleks pidada hübriidseks sihtkohatüübiks, nagu on määratletud selle raamatu sissejuhatuses.

Selle peatüki ülejäänud osas, kui me pole selgesõnaliselt teisiti öelnud, viitab mõiste "teema" Kafka teemale.

Et täielikult mõista, kuidas teemad käituvad ja milliseid tagatisi need annavad, peame esmalt vaatama, kuidas neid Kafkas rakendatakse.
Igal Kafka teemal on oma logi.
Kafkale sõnumeid saatvad tootjad kirjutavad sellesse logisse ja tarbijad loevad logist pidevalt edasi liikuvate osutite abil. Kafka kustutab perioodiliselt logi vanimad osad, olenemata sellest, kas nende osade teateid on loetud või mitte. Kafka disaini keskne osa on see, et maakler ei hooli sellest, kas sõnumeid loetakse või mitte – see on kliendi vastutus.

Mõisteid "logi" ja "osuti" ei kuvata Kafka dokumentatsioon. Neid tuntud termineid kasutatakse siin mõistmise hõlbustamiseks.

See mudel on täiesti erinev ActiveMQ-st, kus kõigi järjekordade sõnumid salvestatakse samasse logisse ja maakler märgib sõnumid pärast nende lugemist kustutatuks.
Kaevame nüüd natukene sügavamale ja vaatame teemalogi lähemalt.
Kafka logi koosneb mitmest vaheseinast (Joonis 3-1). Kafka garanteerib range järjestuse igas vaheseinas. See tähendab, et teatud järjekorras partitsioonile kirjutatud teateid loetakse samas järjekorras. Iga partitsioon on realiseeritud jooksva logifailina, mis sisaldab alamhulk (alamhulk) kõigist selle tootjate poolt teemale saadetud sõnumitest. Loodud teema sisaldab vaikimisi ühte partitsiooni. Vaheseinte idee on Kafka keskne idee horisontaalseks skaleerimiseks.

Sõnumivahendaja mõistmine. Sõnumite saatmise mehaanika õppimine ActiveMQ ja Kafka abil. 3. peatükk. Kafka
Joonis 3-1. Kafka vaheseinad

Kui produtsent saadab sõnumi Kafka teemale, otsustab ta, millisele partitsioonile sõnum saata. Vaatame seda hiljem üksikasjalikumalt.

Sõnumite lugemine

Klient, kes soovib sõnumeid lugeda, haldab nimelist kursorit tarbijarühm, mis viitab nihe sõnumeid partitsioonis. Nihe on järkjärguline asend, mis algab partitsiooni alguses 0-st. See tarbijarühm, millele API-s viidatakse kasutaja määratud rühma_id kaudu, vastab üks loogiline tarbija või süsteem.

Enamik sõnumsidesüsteeme loeb andmeid sihtkohast, kasutades sõnumite paralleelseks töötlemiseks mitut eksemplari ja lõime. Seega on tavaliselt palju sama tarbijarühma jagavaid tarbijajuhte.

Lugemisprobleemi saab esitada järgmiselt:

  • Teemal on mitu partitsiooni
  • Teemat saavad korraga kasutada mitu tarbijarühma
  • Tarbijate rühmal võib olla mitu erinevat eksemplari

See on mittetriviaalne palju-mitmele probleem. Et mõista, kuidas Kafka käsitleb suhteid tarbijarühmade, tarbijajuhtumite ja partitsioonide vahel, vaatame järjest keerukamaid lugemisstsenaariume.

Tarbijad ja tarbijarühmad

Võtame lähtepunktiks ühe partitsiooniga teema (Joonis 3-2).

Sõnumivahendaja mõistmine. Sõnumite saatmise mehaanika õppimine ActiveMQ ja Kafka abil. 3. peatükk. Kafka
Joonis 3-2. Tarbija loeb partitsioonist

Kui tarbija eksemplar loob selle teemaga ühenduse oma rühma ID-ga, määratakse talle selles partitsioonis lugemissektsioon ja nihe. Selle nihke asukoht konfigureeritakse kliendis viimana kõige värskemale asukohale (uusim sõnum) või varaseimale positsioonile (vanim sõnum). Tarbija küsib (küsitlus) teemast sõnumeid, mis põhjustab nende järjestikuse lugemise logist.
Nihkepositsioon antakse regulaarselt tagasi Kafkale ja salvestatakse sõnumitena sisemises teemas _tarbija_kompensatsioonid. Erinevalt tavalisest maaklerist loetud sõnumeid ikka ei kustutata ja klient saab juba vaadatud sõnumeid uuesti töödelda.

Kui teine ​​loogiline tarbija loob ühenduse erineva group_id abil, haldab ta teist osutit, mis on sõltumatu esimesest (Joonis 3-3). Seega toimib Kafka teema järjekorrana, kus on üks tarbija, ja nagu tavaline avaldamise-tellimise (pub-sub) teema, mille tellib mitu tarbijat, ning lisahüve on see, et kõik sõnumid salvestatakse ja neid saab mitu korda töödelda.

Sõnumivahendaja mõistmine. Sõnumite saatmise mehaanika õppimine ActiveMQ ja Kafka abil. 3. peatükk. Kafka
Joonis 3-3. Kaks tarbijat erinevates tarbijarühmades loevad samast partitsioonist

Tarbijad tarbijarühmas

Kui üks tarbija eksemplar loeb partitsioonist andmeid, on sellel kursori üle täielik kontroll ja see töötleb sõnumeid, nagu on kirjeldatud eelmises jaotises.
Kui mitu tarbijate eksemplari ühendati sama group_id-ga ühe partitsiooniga teemaga, siis saab viimati ühenduses olnud eksemplar kursori üle kontrolli ja sellest hetkest saab ta kõik sõnumid (Joonis 3-4).

Sõnumivahendaja mõistmine. Sõnumite saatmise mehaanika õppimine ActiveMQ ja Kafka abil. 3. peatükk. Kafka
Joonis 3-4. Kaks samas tarbijarühmas olevat tarbijat loevad samast partitsioonist

Seda töötlemisviisi, mille puhul tarbijaeksemplaride arv ületab partitsioonide arvu, võib vaadelda kui omamoodi eksklusiivset tarbijat. See võib olla kasulik, kui vajate oma tarbijaeksemplaride "aktiivset-passiivset" (või "kuum-sooja") klastrit, kuigi mitme tarbija paralleelne käitamine ("aktiivne-aktiivne" või "kuum-kuum") on palju tüüpilisem kui tarbijad.

See ülalkirjeldatud sõnumite levitamise käitumine võib olla üllatav võrreldes sellega, kuidas tavaline JMS-i järjekord käitub. Selles mudelis jaotatakse järjekorda saadetud sõnumid kahe tarbija vahel ühtlaselt.

Enamasti, kui loome mitu tarbijajuhtumit, teeme seda kas sõnumite paralleelseks töötlemiseks või lugemiskiiruse suurendamiseks või lugemisprotsessi stabiilsuse suurendamiseks. Kuna partitsioonist saab andmeid lugeda korraga ainult üks tarbija eksemplar, siis kuidas see Kafkas saavutatakse?

Üks võimalus selleks on kasutada ühte tarbijaeksemplari kõigi sõnumite lugemiseks ja nende lõimede kogumile edastamiseks. Kuigi see lähenemisviis suurendab töötlemise läbilaskevõimet, muudab see tarbija loogika keerukamaks ega suurenda lugemissüsteemi töökindlust. Kui üks tarbija eksemplar läheb elektrikatkestuse või sarnase sündmuse tõttu alla, siis lahutamine peatub.

Kanooniline viis selle probleemi lahendamiseks Kafkas on kasutada bОrohkem vaheseinu.

Partitsioneerimine

Sektsioonid on peamine mehhanism teema lugemise ja skaleerimise paralleelseerimiseks, mis ületab ühe maakleri eksemplari ribalaiust. Selle paremaks mõistmiseks vaatleme olukorda, kus on kahe partitsiooniga teema ja üks tarbija tellib selle teema (Joonis 3-5).

Sõnumivahendaja mõistmine. Sõnumite saatmise mehaanika õppimine ActiveMQ ja Kafka abil. 3. peatükk. Kafka
Joonis 3-5. Üks tarbija loeb mitmest partitsioonist

Selle stsenaariumi korral antakse tarbijale mõlemas partitsioonis kontroll tema group_id-le vastavate osutite üle ja ta hakkab lugema sõnumeid mõlemast partitsioonist.
Kui sellesse teemasse lisatakse sama rühma_id jaoks täiendav tarbija, jaotab Kafka ühe partitsiooni esimeselt tarbijalt teisele. Pärast seda loeb iga tarbija eksemplar teema ühest osast (Joonis 3-6).

Tagamaks, et sõnumeid töödeldakse paralleelselt 20 lõimes, vajate vähemalt 20 partitsiooni. Kui vaheseinu on vähem, jäävad teile tarbijad, kellel pole midagi teha, nagu on kirjeldatud varem eksklusiivsete tarbijate arutelus.

Sõnumivahendaja mõistmine. Sõnumite saatmise mehaanika õppimine ActiveMQ ja Kafka abil. 3. peatükk. Kafka
Joonis 3-6. Kaks sama tarbijarühma tarbijat loevad erinevatest sektsioonidest

See skeem vähendab oluliselt Kafka maakleri keerukust võrreldes JMS-i järjekorra säilitamiseks vajaliku sõnumite levitamisega. Siin ei pea te muretsema järgmiste punktide pärast:

  • Milline tarbija peaks saama järgmise sõnumi, võttes aluseks ring-robin jaotuse, eelhankimispuhvrite praeguse võimsuse või eelmiste sõnumite (nagu JMS-i sõnumirühmade puhul).
  • Milliseid sõnumeid millistele tarbijatele saadetakse ja kas need tuleks rikke korral uuesti edastada.

Kafka maakler peab vaid edastama sõnumeid tarbijale, kui viimane seda nõuab.

Nõuded korrektuuri paralleelsusele ja ebaõnnestunud sõnumite uuesti saatmisele ei kao aga kuhugi – vastutus nende eest läheb lihtsalt maaklerilt kliendile. See tähendab, et neid tuleb oma koodis arvesse võtta.

Sõnumite saatmine

Selle sõnumi koostaja vastutab selle üle, millisele partitsioonile sõnum saata. Selle mehhanismi mõistmiseks peame kõigepealt läbi mõtlema, mida me tegelikult saadame.

Kui JMS-is kasutame sõnumistruktuuri koos metaandmetega (päised ja atribuudid) ja põhikoormust sisaldava kehaga (payload), siis Kafkas on sõnum paar "võtmeväärtus". Sõnumi kasulik koormus saadetakse väärtusena. Seevastu võtit kasutatakse peamiselt partitsioonideks ja see peab sisaldama äriloogikaspetsiifiline võtiseotud sõnumite paigutamiseks samasse partitsiooni.

2. peatükis käsitlesime võrgukihlvedude stsenaariumi, kus seotud sündmusi peab töötlema järjekorras üks tarbija:

  1. Kasutajakonto on konfigureeritud.
  2. Raha kantakse kontole.
  3. Tehakse panus, mis võtab kontolt raha välja.

Kui iga sündmus on teemasse postitatud sõnum, on loomulik võti konto ID.
Kui sõnum saadetakse Kafka Producer API abil, edastatakse see partitsioonifunktsioonile, mis sõnumit ja Kafka klastri praegust olekut arvestades tagastab selle partitsiooni ID, kuhu sõnum tuleks saata. Seda funktsiooni rakendatakse Javas partitsiooniliidese kaudu.

See liides näeb välja selline:

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

Sektsioonide juurutus kasutab partitsiooni määramiseks võtme üle vaikimisi üldotstarbelist räsimisalgoritmi või, kui võtit pole määratud, ümardamist. See vaikeväärtus töötab enamikul juhtudel hästi. Küll aga tahad tulevikus ise kirjutada.

Oma partitsioonistrateegia kirjutamine

Vaatame näidet, kus soovite saata metaandmeid koos sõnumi koormusega. Kasulik koormus meie näites on juhis teha sissemakse mängukontole. Juhised on midagi, mille puhul sooviksime olla kindlad, et seda edastamisel ei muudeta, ja tahame olla kindlad, et selle juhise saab algatada ainult usaldusväärne ülesvoolu süsteem. Sel juhul lepivad saatev ja vastuvõttev süsteem kokku allkirja kasutamises sõnumi autentimiseks.
Tavalises JMS-is määratleme lihtsalt atribuudi "sõnumi allkiri" ja lisame selle sõnumile. Kuid Kafka ei paku meile metaandmete edastamise mehhanismi, vaid ainult võtit ja väärtust.

Kuna väärtus on pangaülekande kasulik koormus, mille terviklikkust tahame säilitada, ei jää meil muud üle, kui määratleda võtmes kasutatav andmestruktuur. Eeldades, et partitsiooniks vajame konto ID-d, kuna kõik kontoga seotud sõnumid tuleb töödelda järjekorras, saame järgmise JSON-struktuuri:

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

Kuna allkirja väärtus sõltub kasulikust koormusest, ei rühmita partitsioonide liidese vaikeräsistrateegia seotud sõnumeid usaldusväärselt. Seetõttu peame kirjutama oma strateegia, mis sõelub selle võtme ja jagab accountId väärtuse.

Kafka sisaldab kontrollsummasid, et tuvastada poes olevate sõnumite rikkumine, ja sellel on täielik komplekt turvafunktsioone. Sellegipoolest ilmnevad mõnikord tööstusharuspetsiifilised nõuded, nagu ülaltoodud.

Kasutaja partitsioonistrateegia peab tagama, et kõik seotud sõnumid jõuavad samasse partitsiooni. Kuigi see tundub lihtne, võib nõuet keerulisemaks muuta seotud sõnumite järjestamise tähtsus ja teema partitsioonide arvu fikseerimine.

Teema partitsioonide arv võib aja jooksul muutuda, kuna neid saab lisada, kui liiklus ületab esialgseid ootusi. Seega saab sõnumivõtmeid seostada partitsiooniga, kuhu need algselt saadeti, mis tähendab, et tootjaeksemplaride vahel jagatakse olekuosa.

Teine tegur, mida tuleb arvestada, on sõnumite ühtlane jaotus partitsioonide vahel. Tavaliselt ei jaotata võtmeid sõnumite vahel ühtlaselt ja räsifunktsioonid ei taga sõnumite õiglast jaotust väikese võtmekomplekti puhul.
Oluline on märkida, et olenemata sellest, kui valite sõnumeid poolitada, võib olla vaja eraldajat ennast uuesti kasutada.

Kaaluge nõuet replitseerida andmeid erinevates geograafilistes asukohtades asuvate Kafka klastrite vahel. Sel eesmärgil on Kafkaga kaasas käsurea tööriist nimega MirrorMaker, mida kasutatakse sõnumite lugemiseks ühest klastrist ja teisaldamiseks teise.

MirrorMaker peab mõistma replitseeritud teema võtmeid, et säilitada klastrite vahel paljundamisel sõnumite vahelist suhtelist järjestust, kuna selle teema partitsioonide arv ei pruugi kahes klastris olla sama.

Kohandatud partitsioonistrateegiad on suhteliselt haruldased, kuna vaikimisi räsimine või ümbertöötamine töötab enamiku stsenaariumide puhul hästi. Kui aga vajate tugevaid tellimisgarantiid või vajate kasulikest koormustest metaandmeid eraldada, peaksite partitsioonidega tegelema lähemalt.

Kafka mastaapsuse ja jõudluse eelised tulenevad osa traditsioonilise maakleri kohustuste üleandmisest kliendile. Sel juhul otsustatakse potentsiaalselt seotud sõnumid levitada mitme paralleelselt töötava tarbija vahel.

Selliste nõuetega peavad tegelema ka JMS-i maaklerid. Huvitav on see, et samale tarbijale seotud sõnumite saatmise mehhanism, mida rakendatakse JMS-i sõnumirühmade kaudu (SLB-strateegia variatsioon), nõuab ka saatjalt sõnumite seotuks märkimist. JMS-i puhul vastutab maakler selle seotud sõnumite grupi saatmise eest ühele tarbijale paljudest ja grupi omandiõiguse üleandmise eest, kui tarbija kukub.

Tootjalepingud

Jaotamine pole ainus asi, mida sõnumite saatmisel arvestada. Vaatame Java API klassi Producer meetodeid send():

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

Kohe tuleb märkida, et mõlemad meetodid tagastavad Future, mis näitab, et saatmistoimingut ei tehta kohe. Tulemuseks on see, et iga aktiivse partitsiooni saatmispuhvrisse kirjutatakse teade (ProducerRecord) ja saadetakse maaklerile Kafka klienditeegi taustalõimena. Kuigi see muudab asjad uskumatult kiireks, tähendab see, et kogenematu rakendus võib protsessi peatamise korral sõnumid kaotada.

Nagu alati, on jõudluse hinnaga võimalik saatmistoimingut usaldusväärsemaks muuta. Selle puhvri suuruseks saab määrata 0 ja rakenduse saatmise lõim on sunnitud ootama, kuni sõnumi edastamine maaklerile on lõpule viidud, järgmiselt:

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

Lisateavet sõnumite lugemise kohta

Sõnumite lugemisel on täiendavaid keerukusi, mille üle tuleb spekuleerida. Erinevalt JMS API-st, mis võib vastusena sõnumile käivitada sõnumikuulaja, Tarbija Kafka ainult küsitleb. Vaatame meetodit lähemalt küsitlus ()selleks kasutatakse:

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

Meetodi tagastusväärtus on mitut objekti sisaldav konteineri struktuur tarbija rekord potentsiaalselt mitmest partitsioonist. tarbija rekord on ise võtme-väärtuste paari hoidjaobjekt koos seotud metaandmetega, näiteks partitsiooniga, millest see tuletatakse.

Nagu 2. peatükis arutatud, peame meeles pidama, mis juhtub sõnumitega pärast nende edukat või ebaõnnestunud töötlemist, näiteks kui klient ei saa sõnumit töödelda või kui see katkeb. JMS-is käsitleti seda kinnitusrežiimi kaudu. Maakler kustutab edukalt töödeldud sõnumi või edastab uuesti töötlemata või võltsitud sõnumi (eeldusel, et tehinguid kasutati).
Kafka töötab väga erinevalt. Maakleris sõnumeid pärast korrektuuri ei kustutata ja ebaõnnestumise korral vastutab korrektuurikood ise.

Nagu oleme öelnud, on tarbijarühm seotud logis oleva nihkega. Selle nihkega seotud logi asukoht vastab järgmisele sõnumile, millele vastuseks väljastatakse küsitlus (). Ajapunkt, mil see nihe suureneb, on lugemise jaoks määrav.

Tulles tagasi varem käsitletud lugemismudeli juurde, koosneb sõnumite töötlemine kolmest etapist:

  1. Hankige sõnum lugemiseks.
  2. Töötle sõnumit.
  3. Kinnitage teade.

Kafka tarbijal on konfiguratsioonivõimalus enable.auto.commit. See on sageli kasutatav vaikesäte, nagu ka sõna "auto" sisaldavate sätete puhul.

Enne Kafka 0.10 saatis seda valikut kasutav klient järgmisel kõnel viimase loetud sõnumi nihke küsitlus () pärast töötlemist. See tähendas, et kõiki juba toodud sõnumeid saab uuesti töödelda, kui klient oli neid juba töödelnud, kuid hävitati ootamatult enne helistamist küsitlus (). Kuna maakler ei säilita teadet loetud kordade kohta, ei tea järgmine tarbija, kes selle sõnumi kätte saab, teada, et midagi halba juhtus. Selline käitumine oli pseudotehing. Nihe tehti ainult siis, kui sõnum oli edukalt töödeldud, kuid kui klient katkestas, saadab maakler sama sõnumi uuesti teisele kliendile. See käitumine oli kooskõlas sõnumi edastamise garantiiga "vähemalt korra"

Kafka versioonis 0.10 on kliendi koodi muudetud nii, et kliendi teek käivitab volituse perioodiliselt, nagu on konfigureeritud auto.commit.interval.ms. See käitumine jääb režiimide JMS AUTO_ACKNOWLEDGE ja DUPS_OK_ACKNOWLEDGE vahele. Autocommit kasutamisel võis sõnumeid siduda sõltumata sellest, kas neid tegelikult töödeldi – see võib juhtuda aeglase tarbija puhul. Kui tarbija katkestab, tõmbab sõnumid järgmine tarbija, alustades pühendunud positsioonist, mille tulemuseks võib olla vastamata sõnum. Sel juhul ei kaotanud Kafka sõnumeid, lugemiskood lihtsalt ei töötlenud neid.

Sellel režiimil on sama lubadus, mis versioonil 0.9: sõnumeid saab töödelda, kuid kui see ebaõnnestub, ei pruugita nihet sooritada, mis võib põhjustada kohaletoimetamise kahekordistumist. Mida rohkem sõnumeid täitmisel laadite küsitlus (), seda rohkem seda probleemi.

Nagu on kirjeldatud jaotises "Sõnumite lugemine järjekorrast" lk 21, ei ole sõnumisüsteemis sellist asja nagu ühekordne sõnumi edastamine, kui tõrkerežiime võetakse arvesse.

Kafkas on nihke (nihke) sidumiseks (kehtimiseks) kaks võimalust: automaatselt ja käsitsi. Mõlemal juhul saab sõnumeid töödelda mitu korda, kui sõnum töödeldi, kuid enne kinnitamist ebaõnnestus. Samuti saate sõnumit üldse mitte töödelda, kui sidumine toimus taustal ja teie kood valmis enne selle töötlemist (võib-olla Kafka 0.9 ja varasemates versioonides).

Kafka tarbija API-s saate juhtida käsitsi nihke kinnitamise protsessi, määrates parameetri enable.auto.commit valeks ja kutsudes selgesõnaliselt ühte järgmistest meetoditest:

void commitSync();
void commitAsync();

Kui soovite sõnumit "vähemalt korra" töödelda, tuleb nihe käsitsi sisse viia commitSync()käivitades selle käsu kohe pärast sõnumite töötlemist.

Need meetodid ei võimalda sõnumeid enne nende töötlemist kinnitada, kuid need ei aita kuidagi kõrvaldada võimalikke töötlemise viivitusi, jättes samas tehinguga seotud mulje. Kafkas tehinguid ei toimu. Kliendil ei ole võimalust teha järgmist:

  • Kerige võltssõnum automaatselt tagasi. Tarbijad peavad ise tegelema probleemsetest kasulikest koormustest ja taustasüsteemi katkestustest tulenevate eranditega, kuna nad ei saa loota, et vahendaja edastab sõnumeid uuesti.
  • Saatke ühe tuumatoiminguga sõnumeid mitmele teemale. Nagu varsti näeme, võib erinevate teemade ja partitsioonide juhtimine asuda Kafka klastri erinevates masinates, mis ei koordineeri saatmisel tehinguid. Selle kirjutamise ajal on selle KIP-98 abil võimalikuks muutmiseks veidi tööd tehtud.
  • Ühe teema ühe sõnumi lugemine seostatakse teise sõnumi saatmisega teisele teemale. Kafka arhitektuur sõltub jällegi paljudest sõltumatutest masinatest, mis töötavad ühe bussina ja seda ei üritata varjata. Näiteks puuduvad API-komponendid, mis lubaksid linkida tarbija и Lavastaja tehingus. JMS-is pakub seda objekt istungmillest luuakse Sõnumitootjad и MessageConsumers.

Kui me ei saa tehingutele tugineda, siis kuidas saame pakkuda traditsiooniliste sõnumisüsteemide pakutavale semantikat?

Kui on võimalus, et tarbija tasaarvestus võib suureneda enne sõnumi töötlemist, näiteks tarbija krahhi ajal, siis ei saa tarbija kuidagi teada, kas tema tarbijarühm jättis partitsiooni määramisel sõnumist märkamata. Seega on üks strateegia nihke tagasi kerimine eelmisele positsioonile. Kafka tarbija API pakub selleks järgmisi meetodeid.

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

Meetod otsima () saab kasutada koos meetodiga
OffsetsFor Times(kaart ajatemplidOtsimiseks) tagasikerimine mingisse konkreetsesse minevikuhetkesse.

Kaudselt tähendab selle lähenemisviisi kasutamine, et on väga tõenäoline, et mõnda varem töödeldud sõnumit loetakse ja töödeldakse uuesti. Selle vältimiseks saame kasutada idempotentset lugemist, nagu on kirjeldatud 4. peatükis, et jälgida varem vaadatud sõnumeid ja kõrvaldada duplikaadid.

Teise võimalusena võib teie tarbijakoodi hoida lihtsana, kuni sõnumi kadumine või dubleerimine on vastuvõetav. Arvestades kasutusjuhtumeid, milleks Kafkat tavaliselt kasutatakse, nagu logisündmuste, mõõdikute, klikkide jälgimise jne käsitlemine, mõistame, et üksikute sõnumite kadumine ei avalda tõenäoliselt ümbritsevatele rakendustele olulist mõju. Sellistel juhtudel on vaikeväärtused täiesti vastuvõetavad. Teisest küljest, kui teie rakendus peab makseid saatma, peate hoolikalt hoolitsema iga üksiku sõnumi eest. Kõik taandub kontekstile.

Isiklikud tähelepanekud näitavad, et sõnumite intensiivsuse kasvades iga üksiku sõnumi väärtus väheneb. Suured sõnumid kipuvad olema väärtuslikud, kui neid vaadata koondatud kujul.

Kõrge kättesaadavus

Kafka lähenemisviis kõrgele kättesaadavusele erineb ActiveMQ lähenemisviisist väga palju. Kafka on loodud mastaapsete klastrite ümber, kus kõik maakleri eksemplarid võtavad vastu ja levitavad sõnumeid samal ajal.

Kafka klaster koosneb mitmest eri serverites töötavast maakleri eksemplarist. Kafka töötati välja tavalisel eraldiseisval riistvaral, kus igal sõlmel on oma spetsiaalne salvestusruum. Võrku ühendatud salvestusruumi (SAN) kasutamine ei ole soovitatav, kuna mitu arvutussõlme võivad aja pärast konkureerida.Ыe salvestusintervalle ja tekitada konflikte.

Kafka on alati olemas süsteem. Paljud suured Kafka kasutajad ei sulge kunagi oma klastreid ja tarkvara värskendatakse alati järjestikuse taaskäivitusega. See saavutatakse, tagades sõnumite ja maakleritevahelise suhtluse ühilduvuse eelmise versiooniga.

Serveriklastriga ühendatud maaklerid Loomaaiatalitaja, mis toimib konfiguratsiooniandmete registrina ja mida kasutatakse iga maakleri rollide koordineerimiseks. ZooKeeper ise on hajutatud süsteem, mis pakub kõrget kättesaadavust teabe replikatsiooni kaudu kvoorum.

Põhijuhul luuakse Kafka klastris teema, millel on järgmised omadused:

  • Sektsioonide arv. Nagu varem mainitud, sõltub siin kasutatav täpne väärtus soovitud paralleellugemise tasemest.
  • Replikatsioonitegur (tegur) määrab, mitu maakleri eksemplari klastris peaks sisaldama selle partitsiooni logisid.

Kasutades koordineerimiseks ZooKeepersi, üritab Kafka uusi partitsioone klastri maaklerite vahel õiglaselt jaotada. Seda teeb üks juhtum, mis toimib kontrollerina.

Käitusajal iga teemajaotuse jaoks Kontroller määrata maaklerile rollid juht (juht, meister, saatejuht) ja järgijaid (järgijad, orjad, alluvad). Maakler, kes tegutseb selle partitsiooni juhina, vastutab kõigi tootjate poolt talle saadetud sõnumite vastuvõtmise ja tarbijatele edastamise eest. Kui sõnumid saadetakse teemasektsioonile, kopeeritakse need kõikidesse maaklerisõlmedesse, mis toimivad selle partitsiooni järgijatena. Kutsutakse välja iga sõlm, mis sisaldab partitsiooni logisid koopia. Maakler võib tegutseda mõne partitsiooni juhina ja teiste jaoks järgijana.

Kutsutakse järgija, mis sisaldab kõiki juhi käsutuses olevaid sõnumeid sünkroonitud koopia (replica, mis on sünkroonitud olekus, sünkroonitud koopia). Kui partitsiooni juhina tegutsev maakler läheb alla, võib liidrirolli üle võtta iga maakler, kes on selle partitsiooni jaoks ajakohane või sünkroonitud. See on uskumatult jätkusuutlik disain.

Osa tootja konfiguratsioonist on parameeter acks, mis määrab, mitu koopiat peab sõnumi vastuvõtmist kinnitama (kinnitama), enne kui rakenduse lõim saatmist jätkab: 0, 1 või kõik. Kui see on määratud kõik, siis sõnumi saabumisel saadab juht produtsendile kinnituse niipea, kui ta saab rekordi kinnituse (kinnituse) mitmelt teema seadistusega määratud märguandelt (kaasa arvatud temalt endalt). min.insync.replicas (vaikimisi 1). Kui sõnumit ei õnnestu edukalt kopeerida, teeb tootja rakenduse erandi (NotEnoughReplicas või NotEnoughReplicasAfterAppend).

Tüüpiline konfiguratsioon loob teema replikatsiooniteguriga 3 (1 juht, 2 jälgijat partitsiooni kohta) ja parameetriga min.insync.replicas on seatud väärtusele 2. Sel juhul lubab klaster ühel teemasektsiooni haldaval maakleril alla minna, ilma et see mõjutaks kliendirakendusi.

See toob meid tagasi juba tuttava kompromissi juurde jõudluse ja töökindluse vahel. Replikatsioon toimub jälgijate kinnituste (kinnituste) täiendava ooteaja arvelt. Kuigi, kuna see töötab paralleelselt, on replikatsioonil vähemalt kolmele sõlmele sama jõudlus kui kahele (jättes tähelepanuta võrgu ribalaiuse kasutamise suurenemise).

Seda replikatsiooniskeemi kasutades väldib Kafka nutikalt vajadust kirjutada iga teade toiminguga füüsiliselt kettale sync(). Iga tootja saadetud sõnum kirjutatakse partitsioonilogi, kuid nagu peatükis 2 kirjeldatud, toimub faili kirjutamine algselt operatsioonisüsteemi puhvris. Kui see sõnum kopeeritakse teisele Kafka eksemplarile ja on selle mälus, ei tähenda juhi kadumine, et sõnum ise kaotsi läks – selle saab üle võtta sünkroniseeritud koopia.
Operatsiooni tegemisest keeldumine sync() tähendab, et Kafka saab sõnumeid vastu võtta sama kiiresti kui suudab need mällu kirjutada. Ja vastupidi, mida kauem saate vältida mälu kettale loputamist, seda parem. Sel põhjusel ei ole harvad juhud, kui Kafka maakleritele eraldatakse 64 GB või rohkem mälu. See mälukasutus tähendab, et üks Kafka eksemplar võib hõlpsasti töötada tuhandeid kordi kiiremini kui traditsiooniline sõnumivahendaja.

Kafkat saab konfigureerida ka toimingut rakendama sync() sõnumipakettidele. Kuna Kafkas on kõik paketipõhised, töötab see paljudel kasutusjuhtudel üsna hästi ja on kasulik tööriist kasutajatele, kes nõuavad väga tugevaid garantiisid. Suur osa Kafka puhtast jõudlusest tuleneb sõnumitest, mis saadetakse maaklerile pakettidena ja et neid sõnumeid loetakse maaklerilt järjestikuste plokkidena, kasutades null koopia toimingud (toimingud, mille käigus ei täideta andmete kopeerimist ühest mälupiirkonnast teise). Viimane suurendab jõudlust ja ressursse ning on võimalik ainult läbi logiandmete struktuuri, mis määratleb partitsiooniskeemi.

Kafka klastris on palju parem jõudlus kui ühe Kafka maakleri puhul, kuna teemasektsioonid võivad ulatuda mitmesse erinevasse masinasse.

Tulemused

Selles peatükis vaatlesime, kuidas Kafka arhitektuur kujundab ümber klientide ja maaklerite vahelised suhted, et pakkuda uskumatult tugevat sõnumivahetust, mille läbilaskevõime on mitu korda suurem kui tavalisel sõnumivahendajal. Oleme arutanud funktsioone, mida see selle saavutamiseks kasutab, ja vaatlesime lühidalt seda funktsiooni pakkuvate rakenduste arhitektuuri. Järgmises peatükis vaatleme levinumaid probleeme, mida sõnumipõhised rakendused peavad lahendama, ja arutame nende lahendamise strateegiaid. Peatüki lõpetame kirjeldades, kuidas rääkida sõnumsidetehnoloogiatest üldiselt, et saaksite hinnata nende sobivust teie kasutusjuhtudele.

Eelmine tõlgitud osa: Sõnumivahendaja mõistmine. Sõnumite saatmise mehaanika õppimine ActiveMQ ja Kafka abil. 1. peatükk

Tõlge tehtud: tele.gg/middle_java

Jätkub ...

Küsitluses saavad osaleda ainult registreerunud kasutajad. Logi sissepalun.

Kas teie organisatsioonis kasutatakse Kafkat?

  • Jah

  • ei

  • Varem kasutatud, nüüd mitte

  • Plaanime kasutada

38 kasutajat hääletas. 8 kasutajat jäi erapooletuks.

Allikas: www.habr.com

Lisa kommentaar