Sut daeth Kafka yn realiti

Sut daeth Kafka yn realiti

Hei Habr!

Rwy’n gweithio ar dîm Tinkoff, sy’n datblygu ei ganolfan hysbysu ei hun. Rwy'n datblygu yn Java yn bennaf gan ddefnyddio Spring boot ac yn datrys problemau technegol amrywiol sy'n codi mewn prosiect.

Mae'r rhan fwyaf o'n microwasanaethau yn cyfathrebu â'i gilydd yn anghydamserol trwy frocer negeseuon. Yn flaenorol, gwnaethom ddefnyddio IBM MQ fel brocer, na allai ymdopi â'r llwyth mwyach, ond ar yr un pryd roedd ganddo warantau dosbarthu uchel.

Yn ei le, cynigiwyd Apache Kafka i ni, sydd â photensial graddio uchel, ond, yn anffodus, mae angen dull unigol bron o ffurfweddu ar gyfer gwahanol senarios. Yn ogystal, nid oedd y mecanwaith cyflwyno o leiaf unwaith sy'n gweithio yn Kafka yn ddiofyn yn caniatáu cynnal y lefel ofynnol o gysondeb allan o'r bocs. Nesaf, byddaf yn rhannu ein profiad mewn cyfluniad Kafka, yn benodol, byddaf yn dweud wrthych sut i ffurfweddu a byw gydag union unwaith y cyflwynir.

Dosbarthiad gwarantedig a mwy

Bydd y gosodiadau a drafodir isod yn helpu i atal nifer o broblemau gyda'r gosodiadau cysylltiad rhagosodedig. Ond yn gyntaf hoffwn roi sylw i un paramedr a fydd yn hwyluso dadfyg posibl.

Bydd hyn yn helpu cleient.id ar gyfer Cynhyrchydd a Defnyddiwr. Ar yr olwg gyntaf, gallwch ddefnyddio enw'r cais fel y gwerth, ac yn y rhan fwyaf o achosion bydd hyn yn gweithio. Er bod y sefyllfa pan fydd cais yn defnyddio sawl Defnyddiwr a chithau'n rhoi'r un client.id iddynt, yn arwain at y rhybudd canlynol:

org.apache.kafka.common.utils.AppInfoParser — Error registering AppInfo mbean javax.management.InstanceAlreadyExistsException: kafka.consumer:type=app-info,id=kafka.test-0

Os ydych chi am ddefnyddio JMX mewn cymhwysiad gyda Kafka, yna gallai hyn fod yn broblem. Ar gyfer yr achos hwn, mae'n well defnyddio cyfuniad o enw'r cais ac, er enghraifft, enw'r pwnc fel y gwerth client.id. Mae canlyniad ein cyfluniad i'w weld yn yr allbwn gorchymyn kafka-grwpiau defnyddwyr o gyfleustodau gan Confluent:

Sut daeth Kafka yn realiti

Nawr, gadewch i ni edrych ar y senario ar gyfer cyflwyno neges gwarantedig. Mae gan Gynhyrchydd Kafka baramedr acau, sy'n eich galluogi i ffurfweddu ar ôl faint sy'n cydnabod bod angen i arweinydd y clwstwr ystyried y neges a ysgrifennwyd yn llwyddiannus. Gall y paramedr hwn gymryd y gwerthoedd canlynol:

  • 0 — ni fydd cydnabod yn cael ei ystyried.
  • 1 yw'r paramedr rhagosodedig, dim ond 1 replica sydd angen ei gydnabod.
  • −1 — mae angen cydnabod o bob atgynhyrchiad cydamserol (gosod clwstwr min.insync.replicas).

O'r gwerthoedd a restrir mae'n amlwg mai acciau hafal i −1 sy'n rhoi'r sicrwydd cryfaf na fydd y neges yn cael ei cholli.

Fel y gwyddom i gyd, mae systemau gwasgaredig yn annibynadwy. Er mwyn amddiffyn rhag diffygion dros dro, mae Cynhyrchydd Kafka yn darparu'r opsiwn yn ail geisio, sy'n eich galluogi i osod nifer yr ymgeisiau ail-anfon oddi mewn amser.cyflenwi.ms. Gan fod gan y paramedr ail-geisio werth rhagosodedig o Integer.MAX_VALUE (2147483647), gellir addasu nifer yr ailgeisiadau neges trwy newid delivery.timeout.ms yn unig.

Rydym yn symud tuag at union unwaith y danfoniad

Mae'r gosodiadau a restrir yn caniatáu i'n Cynhyrchydd gyflwyno negeseuon gyda gwarant uchel. Gadewch i ni nawr siarad am sut i sicrhau mai dim ond un copi o neges sy'n cael ei ysgrifennu i bwnc Kafka? Yn yr achos symlaf, i wneud hyn, mae angen i chi osod y paramedr ar y Cynhyrchydd galluogi.idempotence i wir. Mae analluedd yn gwarantu mai dim ond un neges sy'n cael ei hysgrifennu i raniad penodol o un pwnc. Y rhagamod ar gyfer galluogi analluedd yw'r gwerthoedd acks = i gyd, ail geisio > 0, max.in.flight.requests.per.connection ≤ 5. Os na chaiff y paramedrau hyn eu pennu gan y datblygwr, bydd y gwerthoedd uchod yn cael eu gosod yn awtomatig.

Pan fydd analluedd wedi'i ffurfweddu, mae angen sicrhau bod yr un negeseuon yn diweddu yn yr un rhaniadau bob tro. Gellir gwneud hyn trwy osod yr allwedd partitioner.class a'r paramedr i Gynhyrchydd. Gadewch i ni ddechrau gyda'r allwedd. Rhaid iddo fod yr un peth ar gyfer pob cyflwyniad. Gellir cyflawni hyn yn hawdd trwy ddefnyddio unrhyw un o'r IDau busnes o'r post gwreiddiol. Mae gan y paramedr partitioner.class werth rhagosodedig − Rhannwr Rhagosodedig. Gyda'r strategaeth rannu hon, rydym yn gweithredu fel hyn yn ddiofyn:

  • Os yw'r rhaniad wedi'i nodi'n benodol wrth anfon y neges, yna rydym yn ei ddefnyddio.
  • Os nad yw'r rhaniad wedi'i nodi, ond bod yr allwedd wedi'i nodi, dewiswch y rhaniad gan stwnsh yr allwedd.
  • Os nad yw'r rhaniad a'r allwedd wedi'u nodi, dewiswch y rhaniadau fesul un (crwn-robin).

Hefyd, gan ddefnyddio anfon allweddol ac analluog gyda pharamedr max.in.flight.requests.per.connection = 1 yn rhoi prosesu negeseuon symlach i chi ar y Defnyddiwr. Mae'n werth cofio hefyd, os yw rheolaeth mynediad wedi'i ffurfweddu ar eich clwstwr, yna bydd angen hawliau arnoch i ysgrifennu'n analluog at bwnc.

Os nad oes gennych chi'r gallu i anfon trwy allwedd yn sydyn neu os yw'r rhesymeg ar ochr y Cynhyrchydd yn gofyn am gynnal cysondeb data rhwng gwahanol raniadau, yna bydd trafodion yn dod i'r adwy. Yn ogystal, gan ddefnyddio trafodiad cadwyn, gallwch gydamseru cofnod yn Kafka yn amodol, er enghraifft, gyda chofnod yn y gronfa ddata. Er mwyn galluogi anfon trafodaethol at y Cynhyrchydd, rhaid iddo fod yn analluog ac wedi'i osod yn ychwanegol trafodol.id. Os oes gan eich clwstwr Kafka reolaeth mynediad wedi'i ffurfweddu, yna bydd angen caniatâd ysgrifennu ar gyfer cofnod trafodion, fel cofnod analluog, y gellir ei roi trwy fwgwd gan ddefnyddio'r gwerth sydd wedi'i storio yn trafodiad.id.

Yn ffurfiol, gellir defnyddio unrhyw linyn, fel enw'r cais, fel dynodwr trafodiad. Ond os byddwch chi'n lansio sawl achos o'r un cais gyda'r un trafodiad.id, yna bydd yr achos cyntaf a lansiwyd yn cael ei atal gyda gwall, gan y bydd Kafka yn ei ystyried yn broses zombie.

org.apache.kafka.common.errors.ProducerFencedException: Producer attempted an operation with an old epoch. Either there is a newer producer with the same transactionalId, or the producer's transaction has been expired by the broker.

I ddatrys y broblem hon, rydym yn ychwanegu ôl-ddodiad i enw'r cais ar ffurf yr enw gwesteiwr, a gawn o newidynnau amgylchedd.

Mae'r cynhyrchydd wedi'i ffurfweddu, ond dim ond cwmpas y neges y mae trafodion ar Kafka yn ei reoli. Waeth beth fo statws y trafodiad, mae'r neges yn mynd i'r pwnc ar unwaith, ond mae ganddi nodweddion system ychwanegol.

Er mwyn atal negeseuon o'r fath rhag cael eu darllen gan y Defnyddiwr o flaen amser, mae angen iddo osod y paramedr unigedd.lefel i werth darllen_ymrwymedig. Bydd Defnyddiwr o'r fath yn gallu darllen negeseuon nad ydynt yn drafodion fel o'r blaen, a negeseuon trafodaethol dim ond ar ôl ymrwymiad.
Os ydych chi wedi gosod yr holl osodiadau a restrir yn gynharach, yna rydych chi wedi'u ffurfweddu'n union ar ôl eu danfon. Llongyfarchiadau!

Ond mae un naws arall. Transactional.id, y gwnaethom ei ffurfweddu uchod, yw rhagddodiad y trafodiad mewn gwirionedd. Ar y rheolwr trafodion, mae rhif dilyniant yn cael ei ychwanegu ato. Rhoddir y dynodwr a dderbyniwyd i trafodol.id.darfod.ms, sydd wedi'i ffurfweddu ar glwstwr Kafka ac sydd â gwerth rhagosodedig o “7 diwrnod”. Os nad yw'r cais wedi derbyn unrhyw negeseuon yn ystod y cyfnod hwn, yna pan fyddwch chi'n ceisio'r anfoniad trafodion nesaf byddwch chi'n ei dderbyn InvalidPidMappingException. Yna bydd y cydlynydd trafodion yn cyhoeddi rhif dilyniant newydd ar gyfer y trafodiad nesaf. Fodd bynnag, mae'n bosibl y bydd y neges yn cael ei cholli os nad yw'r InvalidPidMappingException yn cael ei drin yn gywir.

Yn lle cyfansymiau

Fel y gallwch weld, nid yw'n ddigon anfon negeseuon at Kafka yn unig. Mae angen i chi ddewis cyfuniad o baramedrau a bod yn barod i wneud newidiadau cyflym. Yn yr erthygl hon, ceisiais ddangos yn fanwl y gosodiad dosbarthu yn union unwaith a disgrifiais nifer o broblemau gyda'r cyfluniadau client.id a drafodional.id y daethom ar eu traws. Isod mae crynodeb o'r gosodiadau Cynhyrchwyr a Defnyddwyr.

Cynhyrchydd:

  1. aciau = holl
  2. yn ail geisio > 0
  3. galluogi.idempotence = gwir
  4. max.in.flight.requests.per.connection ≤ 5 (1 ar gyfer anfon trefnus)
  5. trafodaethal.id = ${application-name} - ${ gwesteiwr}

Defnyddiwr:

  1. unigedd.level = read_committed

Er mwyn lleihau gwallau mewn cymwysiadau yn y dyfodol, gwnaethom ein deunydd lapio ein hunain dros gyfluniad y gwanwyn, lle mae gwerthoedd ar gyfer rhai o'r paramedrau rhestredig eisoes wedi'u gosod.

Dyma un neu ddau o ddeunyddiau ar gyfer hunan-astudio:

Ffynhonnell: hab.com

Ychwanegu sylw