RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet

В senaste artikeln vi tittade på RabbitMQ-klustring för feltolerans och hög tillgänglighet. Låt oss nu gräva djupt i Apache Kafka.

Här är replikeringsenheten partitionen. Varje ämne har ett eller flera avsnitt. Varje sektion har en ledare med eller utan följare. När du skapar ett ämne anger du antalet partitioner och replikeringskoefficienten. Det vanliga värdet är 3, vilket betyder tre repliker: en ledare och två följare.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 1. Fyra sektioner är fördelade på tre mäklare

Alla läs- och skrivförfrågningar går till ledaren. Följare skickar regelbundet förfrågningar till ledaren för att få de senaste meddelandena. Konsumenter vänder sig aldrig till följare, de senare existerar bara för redundans och feltolerans.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet

Partitionsfel

När en mäklare misslyckas misslyckas ofta ledarna för flera sektioner. I var och en av dem blir en följare från en annan nod ledare. I själva verket är detta inte alltid fallet, eftersom synkroniseringsfaktorn också påverkar: om det finns synkroniserade följare, och om inte, om det är tillåtet att byta till en osynkroniserad replika. Men låt oss inte komplicera saker nu.

Mäklare 3 lämnar nätverket och en ny ledare väljs för sektion 2 hos mäklare 2.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 2. Mäklare 3 dör och hans anhängare på mäklare 2 väljs till ny ledare för parti 2

Då lämnar mäklare 1 och även sektion 1 förlorar sin ledare, vars roll övergår till mäklare 2.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 3. Det finns en mäklare kvar. Alla ledare är på en mäklare med noll redundans

När mäklare 1 kommer tillbaka online lägger den till fyra följare, vilket ger viss redundans till varje partition. Men alla ledare var fortfarande kvar på mäklare 2.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 4. Ledare är kvar på mäklare 2

När mäklare 3 kommer upp är vi tillbaka till tre repliker per partition. Men alla ledare är fortfarande på mäklare 2.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 5. Obalanserad placering av ledare efter återställandet av mäklare 1 och 3

Kafka har ett verktyg för bättre ombalansering av ledare än RabbitMQ. Där var du tvungen att använda ett plugin eller skript från tredje part som ändrade policyerna för att migrera masternoden genom att minska redundansen under migreringen. Dessutom, för stora köer var vi tvungna att acceptera otillgänglighet under synkronisering.

Kafka har konceptet "föredragna repliker" för ledarrollen. När ämnespartitioner skapas försöker Kafka fördela ledare jämnt över noder och markerar de första ledarna som föredragna. Med tiden, på grund av serverstarter, fel och anslutningsavbrott, kan ledare hamna på andra noder, som i det extrema fallet som beskrivs ovan.

För att fixa detta erbjuder Kafka två alternativ:

  • alternativ auto.leader.rebalance.enable=true tillåter styrnoden att automatiskt omfördela ledare tillbaka till föredragna repliker och därigenom återställa enhetlig fördelning.
  • Administratören kan köra skriptet kafka-preferred-replica-election.sh för manuell omplacering.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 6. Repliker efter ombalansering

Detta var en förenklad version av misslyckandet, men verkligheten är mer komplex, även om det inte finns något för komplicerat här. Allt handlar om synkroniserade repliker (In-Sync Replicas, ISR).

Synkroniserade repliker (ISR)

En ISR är en uppsättning repliker av en partition som anses vara "synkroniserad" (synk). Det finns en ledare, men det kanske inte finns anhängare. En följare anses synkroniserad om den har gjort exakta kopior av alla ledarens meddelanden innan intervallet löper ut replica.lagtime.max.ms.

En följare tas bort från ISR-uppsättningen om den:

  • gjorde inte en begäran om att välja för intervallet replica.lagtime.max.ms (förmodas död)
  • lyckades inte uppdatera under intervallet replica.lagtime.max.ms (anses långsamt)

Följare gör samplingsförfrågningar under intervallet replica.fetch.wait.max.ms, som är standard på 500ms.

För att tydligt förklara syftet med ISR måste vi titta på bekräftelser från producenten och några felscenarier. Producenterna kan välja när mäklaren skickar bekräftelse:

  • acks=0, bekräftelse skickas inte
  • acks=1, bekräftelse skickas efter att ledaren har skrivit ett meddelande till sin lokala logg
  • acks=all, bekräftelse skickas efter att alla repliker i ISR ​​har skrivit meddelandet till de lokala loggarna

I Kafka-terminologi, om ISR har sparat ett meddelande, är det "begått". Acks=all är det säkraste alternativet, men lägger också till ytterligare fördröjning. Låt oss titta på två exempel på misslyckanden och hur de olika "acks"-alternativen interagerar med ISR-konceptet.

Acks=1 och ISR

I det här exemplet kommer vi att se att om ledaren inte väntar på att varje meddelande från alla följare ska sparas, så är dataförlust möjlig om ledaren misslyckas. Navigering till en osynkroniserad följare kan aktiveras eller inaktiveras genom inställning oren.ledare.val.aktivera.

I det här exemplet har tillverkaren värdet acks=1. Avsnittet är fördelat på alla tre mäklare. Broker 3 ligger efter, den synkroniserades med ledaren för åtta sekunder sedan och är nu 7456 meddelanden efter. Mäklare 1 var bara en sekund bakom. Vår producent skickar ett meddelande och får snabbt ett ack tillbaka, utan överhead av långsamma eller döda följare som ledaren inte väntar på.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 7. ISR med tre repliker

Broker 2 misslyckas och producenten får ett anslutningsfel. Efter att ledarskapet övergått till mäklare 1 förlorar vi 123 meddelanden. Följaren på mäklare 1 var en del av ISR, men var inte helt synkroniserad med ledaren när den föll.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 8. Meddelanden går förlorade när den kraschar

I konfiguration bootstrap.servrar Tillverkaren har flera mäklare listade och kan fråga en annan mäklare som är ny sektionsledare. Den upprättar sedan en anslutning till mäklare 1 och fortsätter att skicka meddelanden.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 9. Skicka meddelanden återupptas efter en kort paus

Broker 3 ligger ännu längre efter. Den gör hämtningsförfrågningar men kan inte synkronisera. Detta kan bero på långsam nätverksanslutning mellan mäklare, lagringsproblem etc. Det tas bort från ISR. Nu består ISR av en kopia - ledaren! Tillverkaren fortsätter att skicka meddelanden och ta emot bekräftelser.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 10. Följare på mäklare 3 tas bort från ISR

Mäklare 1 går ner och ledarrollen går till mäklare 3 med förlusten av 15286 meddelanden! Tillverkaren får ett anslutningsfelmeddelande. Övergången till en ledare utanför ISR var endast möjlig på grund av inställningen unclean.leader.election.enable=true. Om den är installerad i falsk, då skulle övergången inte inträffa och alla läs- och skrivförfrågningar skulle avvisas. I det här fallet väntar vi på att mäklare 1 ska återkomma med sin intakta data i repliken, som återigen tar över ledarskapet.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 11. Mäklare 1 faller. När ett fel inträffar går ett stort antal meddelanden förlorade

Producenten upprättar en förbindelse med den sista mäklaren och ser att han nu är ledare för sektionen. Han börjar skicka meddelanden till mäklare 3.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 12. Efter en kort paus skickas meddelanden igen till sektion 0

Vi såg att, förutom korta avbrott för att etablera nya förbindelser och söka efter en ny ledare, skickade tillverkaren hela tiden meddelanden. Denna konfiguration säkerställer tillgänglighet på bekostnad av konsekvens (datasäkerhet). Kafka förlorade tusentals meddelanden men fortsatte att acceptera nya skrivningar.

Acks=all och ISR

Låt oss upprepa detta scenario igen, men med acks=alla. Broker 3 har en genomsnittlig latens på fyra sekunder. Tillverkaren skickar ett meddelande med acks=alla, och får nu inget snabbt svar. Ledaren väntar på att meddelandet ska sparas av alla repliker i ISR.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 13. ISR med tre kopior. Den ena är långsam, vilket resulterar i inspelningsförseningar

Efter fyra sekunders ytterligare fördröjning skickar mäklare 2 ett ack. Alla repliker är nu helt uppdaterade.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 14. Alla repliker sparar meddelanden och skickar ack

Mäklare 3 hamnar nu längre efter och tas bort från ISR. Latensen reduceras avsevärt eftersom det inte finns några långsamma repliker kvar i ISR. Mäklare 2 väntar nu bara på mäklare 1, och han har en genomsnittlig fördröjning på 500 ms.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 15. Repliken på mäklare 3 tas bort från ISR

Sedan faller mäklare 2 och ledarskapet övergår till mäklare 1 utan att meddelanden försvinner.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 16. Mäklare 2 faller

Tillverkaren hittar en ny ledare och börjar skicka meddelanden till honom. Latensen reduceras ytterligare eftersom ISR nu består av en replik! Därför alternativet acks=alla lägger inte till redundans.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 17. Replika på mäklare 1 tar ledningen utan att tappa meddelanden

Sedan kraschar mäklare 1 och ledningen går till mäklare 3 med en förlust på 14238 meddelanden!

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 18. Mäklare 1 dör och ledarskapsövergång med orena miljöer resulterar i omfattande dataförlust

Vi kunde inte installera alternativet oren.ledare.val.aktivera till mening sann. Som standard är det lika falsk. inställningar acks=alla с unclean.leader.election.enable=true ger tillgänglighet med viss extra datasäkerhet. Men som ni ser kan vi fortfarande tappa meddelanden.

Men vad händer om vi vill öka datasäkerheten? Du kan sätta unclean.leader.election.enable = falskt, men detta kommer inte nödvändigtvis att skydda oss från dataförlust. Om ledaren föll hårt och tog data med sig, så är meddelanden fortfarande förlorade, plus att tillgängligheten går förlorad tills administratören återställer situationen.

Det är bättre att se till att alla meddelanden är redundanta och annars kassera inspelningen. Då är, åtminstone från mäklarens synvinkel, dataförlust endast möjlig vid två eller flera samtidiga misslyckanden.

Acks=all, min.insync.replicas och ISR

Med ämneskonfiguration min.insync.repliker Vi ökar nivån på datasäkerheten. Låt oss gå igenom den sista delen av det tidigare scenariot igen, men den här gången med min.insync.replicas=2.

Så mäklare 2 har en replikledare och följaren på mäklare 3 tas bort från ISR.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 19. ISR från två kopior

Mäklare 2 faller och ledarskapet övergår till mäklare 1 utan förlust av meddelanden. Men nu består ISR bara av en kopia. Detta uppfyller inte minimiantalet för att ta emot poster, och därför svarar mäklaren på skrivförsöket med ett fel NotEnoughReplicas.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 20. Antalet ISR är en lägre än vad som anges i min.insync.replicas

Denna konfiguration offrar tillgänglighet för konsekvens. Innan vi bekräftar ett meddelande ser vi till att det är skrivet till minst två repliker. Detta ger tillverkaren mycket mer förtroende. Här är meddelandeförlust endast möjlig om två repliker misslyckas samtidigt under ett kort intervall tills meddelandet replikeras till en ytterligare följare, vilket är osannolikt. Men om du är superparanoid kan du ställa in replikeringsfaktorn till 5, och min.insync.repliker med 3. Här måste tre mäklare falla samtidigt för att förlora rekordet! Naturligtvis betalar du för denna tillförlitlighet med ytterligare latens.

När tillgänglighet är nödvändigt för datasäkerhet

Som i fall med RabbitMQ, ibland är tillgänglighet nödvändig för datasäkerhet. Här är vad du behöver tänka på:

  • Kan utgivaren bara returnera ett fel och låta uppströmstjänsten eller användaren försöka igen senare?
  • Kan utgivaren spara meddelandet lokalt eller i en databas för att försöka igen senare?

Om svaret är nej, förbättrar optimering av tillgänglighet datasäkerheten. Du kommer att förlora mindre data om du väljer tillgänglighet istället för att inte spela in. Allt handlar alltså om att hitta en balans, och beslutet beror på den specifika situationen.

Betydelsen av ISR

ISR-sviten låter dig välja den optimala balansen mellan datasäkerhet och latens. Säkerställ till exempel tillgänglighet i händelse av fel på majoriteten av replikerna, minimera effekten av döda eller långsamma repliker när det gäller latens.

Vi väljer själva innebörden replica.lagtime.max.ms efter dina behov. I huvudsak betyder denna parameter hur mycket fördröjning vi är villiga att acceptera när acks=alla. Standardvärdet är tio sekunder. Om detta är för långt för dig kan du minska det. Då kommer frekvensen av förändringar i ISR ​​att öka, eftersom följare kommer att tas bort och läggas till oftare.

RabbitMQ är helt enkelt en uppsättning speglar som behöver replikeras. Långsamma speglar introducerar ytterligare latens, och döda speglar kan vänta tills paketen som kontrollerar tillgängligheten för varje nod (nettick) svarar. ISR är ett intressant sätt att undvika dessa latensproblem. Men vi riskerar att förlora redundans eftersom ISR bara kan krympa till ledaren. För att undvika denna risk, använd inställningen min.insync.repliker.

Kundanslutningsgaranti

I inställningarna bootstrap.servrar producent och konsument kan ange flera mäklare för att ansluta kunder. Tanken är att när en nod går ner finns det flera reservdelar kvar med vilka klienten kan öppna en anslutning. Dessa är inte nödvändigtvis sektionsledare, utan helt enkelt en språngbräda för initial laddning. Klienten kan fråga dem vilken nod som är värd för läs/skrivpartitionsledaren.

I RabbitMQ kan klienter ansluta till vilken nod som helst, och intern routing skickar förfrågan dit den behöver gå. Det betyder att du kan installera en lastbalanserare framför RabbitMQ. Kafka kräver att klienter ansluter till noden som är värd för motsvarande partitionsledare. I en sådan situation kan du inte installera en lastbalanserare. Lista bootstrap.servrar Det är viktigt att klienter kan komma åt och hitta rätt noder efter ett fel.

Kafka konsensusarkitektur

Hittills har vi inte funderat på hur klustret får veta om mäklarens fall och hur en ny ledare väljs. För att förstå hur Kafka fungerar med nätverkspartitioner måste du först förstå konsensusarkitekturen.

Varje Kafka-kluster distribueras tillsammans med ett Zookeeper-kluster, som är en distribuerad konsensustjänst som gör att systemet kan nå konsensus om ett visst tillstånd, och prioriterar konsekvens framför tillgänglighet. Samtycke från en majoritet av Zookeeper-noderna krävs för att godkänna läs- och skrivoperationer.

Zookeeper lagrar klustrets tillstånd:

  • Lista över ämnen, avsnitt, konfiguration, aktuella ledare repliker, föredragna repliker.
  • Klustermedlemmar. Varje mäklare pingar Zookeeper-klustret. Om den inte tar emot en ping inom en angiven tidsperiod, registrerar Zookeeper mäklaren som otillgänglig.
  • Välja huvud- och reservnoder för styrenheten.

Kontrollnoden är en av Kafka-mäklarna som är ansvarig för att välja replikledare. Zookeeper skickar meddelanden till kontrollanten om klustermedlemskap och ämnesändringar, och kontrollanten måste agera på dessa ändringar.

Låt oss till exempel ta ett nytt ämne med tio partitioner och en replikeringsfaktor på 3. Kontrollanten måste välja en ledare för varje partition, och försöka fördela ledarna optimalt bland mäklarna.

För varje sektionskontroller:

  • uppdaterar information i Zookeeper om ISR och ledare;
  • Skickar ett LeaderAndISRCommand till varje mäklare som är värd för en replik av denna partition, och informerar mäklarna om ISR och ledaren.

När en mäklare med en ledare faller, skickar Zookeeper ett meddelande till kontrollanten och den väljer en ny ledare. Återigen uppdaterar styrenheten först Zookeeper och skickar sedan ett kommando till varje mäklare som meddelar dem om ledarskapsbytet.

Varje ledare ansvarar för att rekrytera ISR. inställningar replica.lagtime.max.ms avgör vem som kommer in där. När ISR ändras, sänder ledaren ny information till Zookeeper.

Zookeeper informeras alltid om eventuella förändringar så att i händelse av ett misslyckande övergår ledningen smidigt till en ny ledare.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 21. Kafka Consensus

Replikeringsprotokoll

Att förstå detaljerna i replikeringen hjälper dig att bättre förstå potentiella scenarier för dataförlust.

Samplingsfrågor, Log End Offset (LEO) och Highwater Mark (HW)

Vi ansåg att följare med jämna mellanrum skickar hämtningsförfrågningar till ledaren. Standardintervallet är 500ms. Detta skiljer sig från RabbitMQ genom att i RabbitMQ initieras replikering inte av köspegeln utan av mastern. Mästaren skjuter ändringar till speglarna.

Ledaren och alla följare sparar Log End Offset (LEO) och Highwater (HW)-etiketten. LEO-märket lagrar förskjutningen av det sista meddelandet i den lokala repliken, och HW:n håller förskjutningen för den senaste commit. Kom ihåg att meddelandet måste finnas kvar i alla ISR-repliker för att få status. Det betyder att LEO vanligtvis ligger något före HW.

När ledaren får ett meddelande lagras det lokalt. Följaren gör en hämtningsförfrågan genom att sända sin LEO. Ledaren skickar sedan en grupp meddelanden med start från denna LEO och sänder även den aktuella HW. När ledaren får information om att alla repliker har lagrat meddelandet vid den givna offseten, flyttar den HW-märket. Endast ledaren kan flytta HW, och så kommer alla följare att veta det aktuella värdet i svaren på deras begäran. Detta innebär att följare kan släpa efter ledaren i både budskap och HW-kunskap. Konsumenter får endast meddelanden upp till nuvarande HW.

Observera att "bevarad" betyder skrivet till minnet, inte till disk. För prestanda synkroniserar Kafka till disk med ett specifikt intervall. RabbitMQ har också ett sådant intervall, men det kommer att skicka en bekräftelse till utgivaren först efter att mastern och alla speglar har skrivit meddelandet till disken. Kafka-utvecklarna, av prestandaskäl, bestämde sig för att skicka ett ack så snart meddelandet skrivs till minnet. Kafka slår vad om att redundans uppväger risken för att kortvarigt lagra bekräftade meddelanden endast i minnet.

Ledarens misslyckande

När en ledare faller meddelar Zookeeper kontrollanten och den väljer en ny ledarereplik. Den nya ledaren sätter ett nytt HW-märke enligt sin LEO. Följare får sedan information om den nya ledaren. Beroende på versionen av Kafka kommer följaren att välja ett av två scenarier:

  1. Den kommer att trunkera den lokala loggen till en känd HW och skicka en begäran till den nya ledaren om meddelanden efter detta märke.
  2. Kommer att skicka en förfrågan till ledaren att ta reda på HW vid den tidpunkt då han valdes till ledare, och sedan trunkera loggen till denna offset. Den kommer sedan att börja göra periodiska hämtningsförfrågningar med början på denna offset.

En följare kan behöva trunkera loggen av följande skäl:

  • När en ledare misslyckas vinner den första anhängaren i ISR-uppsättningen registrerad hos Zookeeper valet och blir ledare. Alla följare på ISR, även om de anses vara "synkroniserade", kanske inte har fått kopior av alla meddelanden från den tidigare ledaren. Det är fullt möjligt att den utvalda följaren inte har den mest uppdaterade kopian. Kafka ser till att det inte finns någon skillnad mellan repliker. För att undvika diskrepanser måste varje följare alltså trunkera sin logg till HW-värdet för den nya ledaren vid tidpunkten för hans val. Detta är ytterligare en anledning till att ställa in acks=alla så viktigt för konsistensen.
  • Meddelanden skrivs regelbundet till disk. Om alla klusternoder misslyckas samtidigt, kommer repliker med olika förskjutningar att lagras på diskarna. Det är möjligt att när mäklare kommer tillbaka online kommer den nya ledaren som väljs att ligga bakom sina följare eftersom han sparades till disk före de andra.

Återförening med klustret

När de återansluter sig till klustret gör replikerna samma sak som när en ledare misslyckas: de kontrollerar ledarens replik och trunkerar sin logg till dess HW (vid valtillfället). I jämförelse behandlar RabbitMQ på samma sätt återförenade noder som helt nya. I båda fallen kasserar mäklaren alla befintliga tillstånd. Om automatisk synkronisering används måste mastern replikera absolut allt aktuellt innehåll till den nya spegeln i en "låt hela världen vänta"-metod. Mastern accepterar inga läs- eller skrivoperationer under denna operation. Detta tillvägagångssätt skapar problem i stora köer.

Kafka är en distribuerad logg och i allmänhet lagrar den fler meddelanden än en RabbitMQ-kö, där data tas bort från kön efter att den har lästs. Aktiva köer bör förbli relativt små. Men Kafka är en logg med sin egen lagringspolicy, som kan ställa in en period på dagar eller veckor. Tillvägagångssättet för köblockering och fullständig synkronisering är absolut oacceptabelt för en distribuerad logg. Istället trunkerar Kafka-anhängare helt enkelt sin logg till ledarens HW (vid tiden för hans val) om deras kopia ligger före ledaren. I det mer troliga fallet, när följaren är efter, börjar den helt enkelt göra hämtningsförfrågningar som börjar med sin nuvarande LEO.

Nya eller återanslutna följare börjar utanför ISR och deltar inte i commits. De arbetar helt enkelt tillsammans med gruppen och tar emot meddelanden så snabbt de kan tills de kommer ikapp ledaren och går in i ISR. Det finns ingen inlåsning och du behöver inte kasta all din data.

Förlust av anslutning

Kafka har fler komponenter än RabbitMQ, så det har en mer komplex uppsättning beteenden när klustret kopplas bort. Men Kafka designades ursprungligen för kluster, så lösningarna är väldigt genomtänkta.

Nedan finns flera scenarier för anslutningsfel:

  • Scenario 1: Följaren ser inte ledaren, men ser fortfarande djurskötaren.
  • Scenario 2: Ledaren ser inga följare, men ser fortfarande Zookeeper.
  • Scenario 3: Följaren ser ledaren, men ser inte djurskötaren.
  • Scenario 4: Ledaren ser anhängarna, men ser inte djurskötaren.
  • Scenario 5: Följaren är helt skild från både andra Kafka-noder och Zookeeper.
  • Scenario 6: Ledaren är helt skild från både andra Kafka-noder och Zookeeper.
  • Scenario 7: Kafka-kontrollernoden kan inte se en annan Kafka-nod.
  • Scenario 8: Kafka-kontrollern ser inte Zookeeper.

Varje scenario har sitt eget beteende.

Scenario 1: Följare ser inte ledaren, men ser fortfarande Zookeeper

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 22. Scenario 1: ISR av tre repliker

Anslutningsfelet skiljer mäklare 3 från mäklare 1 och 2, men inte från Zookeeper. Broker 3 kan inte längre skicka hämtningsförfrågningar. Efter att tiden har gått replica.lagtime.max.ms den tas bort från ISR och deltar inte i meddelandebekräftelser. När anslutningen är återställd kommer den att återuppta hämtningsförfrågningar och ansluta sig till ISR när den kommer ikapp ledaren. Zookeeper kommer att fortsätta att ta emot ping och anta att mäklaren lever och mår.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 23. Scenario 1: Mäklaren tas bort från ISR om ingen hämtningsförfrågan tas emot från den inom replica.lag.time.max.ms-intervallet

Det finns ingen delad hjärna eller nodupphängning som i RabbitMQ. Istället minskar redundansen.

Scenario 2: Ledaren ser inga följare, men ser fortfarande Zookeeper

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 24. Scenario 2. Ledare och två följare

En sammanbrott i nätverksanslutning skiljer ledaren från anhängarna, men mäklaren kan fortfarande se Zookeeper. Som i det första scenariot krymper ISR, men denna gång bara till ledaren eftersom alla följare slutar skicka hämtningsförfrågningar. Återigen, det finns ingen logisk uppdelning. Istället försvinner redundansen för nya meddelanden tills anslutningen återställs. Zookeeper fortsätter att ta emot plingar och tror att mäklaren lever och mår.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 25. Scenario 2. ISR har bara krympt till ledaren

Scenario 3. Följare ser ledaren, men ser inte djurskötaren

Följaren är skild från Zookeeper, men inte från mäklaren med ledaren. Som ett resultat fortsätter följaren att göra hämtningsförfrågningar och vara medlem i ISR. Zookeeper tar inte längre emot pingar och registrerar en mäklarkrasch, men eftersom det bara är en följare blir det inga konsekvenser efter återhämtning.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 26. Scenario 3: Följaren fortsätter att skicka hämtningsförfrågningar till ledaren

Scenario 4. Ledaren ser följare, men ser inte Zookeeper

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 27. Scenario 4. Ledare och två följare

Ledaren är skild från Zookeeper, men inte från mäklare med följare.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 28. Scenario 4: Ledare isolerad från Zookeeper

Efter en tid kommer Zookeeper att registrera ett mäklarfel och meddela kontrollanten om det. Han kommer att välja en ny ledare bland sina anhängare. Den ursprungliga ledaren kommer dock fortsätta att tro att det är ledaren och kommer att fortsätta att ta emot bidrag från acks=1. Följare skickar inte längre hämtningsförfrågningar till honom, så han kommer att betrakta dem som döda och försöka krympa ISR till sig själv. Men eftersom den inte har en koppling till Zookeeper, kommer den inte att kunna göra detta, och kommer vid den tidpunkten att vägra att acceptera några ytterligare bidrag.

meddelanden acks=alla kommer inte att få en bekräftelse eftersom ISR först slår på alla repliker och meddelanden inte når dem. När den ursprungliga ledaren försöker ta bort dem från ISR kommer den inte att kunna göra det och kommer att sluta acceptera några meddelanden alls.

Klienter märker snart förändringen i ledaren och börjar skicka poster till den nya servern. När nätverket har återställts ser den ursprungliga ledaren att den inte längre är en ledare och trunkerar sin logg till det HW-värde som den nya ledaren hade vid tidpunkten för misslyckandet med att undvika loggdivergens. Den kommer sedan att börja skicka hämtningsförfrågningar till den nya ledaren. Alla poster från den ursprungliga ledaren som inte replikeras till den nya ledaren går förlorade. Det vill säga meddelanden som inte bekräftades av den ursprungliga ledaren under de få sekunderna när två ledare arbetade kommer att gå förlorade.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 29. Scenario 4. Ledaren på mäklare 1 blir en följare efter att nätverket har återställts

Scenario 5: Följaren är helt skild från både andra Kafka-noder och Zookeeper

Följaren är helt isolerad från både andra Kafka-noder och Zookeeper. Han tar helt enkelt bort sig själv från ISR tills nätverket är återställt och kommer sedan ikapp de andra.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 30. Scenario 5: Isolerad följare tas bort från ISR

Scenario 6: Ledaren är helt skild från både andra Kafka-noder och Zookeeper

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 31. Scenario 6. Ledare och två följare

Ledaren är helt isolerad från sina anhängare, kontrollanten och djurskötaren. Under en kort period kommer den att fortsätta att ta emot anmälningar från acks=1.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 32. Scenario 6: Isolera ledaren från andra Kafka- och Zookeeper-noder

Har inte fått förfrågningar efter utgången replica.lagtime.max.ms, kommer den att försöka krympa ISR till sig själv, men kommer inte att kunna göra det eftersom det inte finns någon kommunikation med Zookeeper, då kommer den att sluta acceptera skrivningar.

Under tiden kommer Zookeeper att markera den isolerade mäklaren som död och kontrollanten kommer att välja en ny ledare.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 33. Scenario 6. Två ledare

Den ursprungliga ledaren kan acceptera bidrag i några sekunder, men slutar sedan acceptera meddelanden. Klienter uppdateras var 60:e sekund med de senaste metadata. De kommer att informeras om ledarebytet och kommer att börja skicka bidrag till den nya ledaren.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 34. Scenario 6: Tillverkare byter till en ny ledare

Alla bekräftade poster gjorda av den ursprungliga ledaren sedan anslutningsförlusten förloras. När nätverket är återställt kommer den ursprungliga ledaren att upptäcka genom Zookeeper att den inte längre är ledaren. Sedan kommer den att trunkera sin logg till den nya ledarens HW vid valtillfället och börja skicka förfrågningar som en följare.

RabbitMQ vs Kafka: Feltolerans och hög tillgänglighet
Ris. 35. Scenario 6: Den ursprungliga ledaren blir en efterföljare efter att nätverksanslutningen har återställts

I denna situation kan logisk separation inträffa under en kort period, men endast om acks=1 и min.insync.repliker även 1. Logisk separation upphör automatiskt antingen efter att nätverket har återställts, när den ursprungliga ledaren inser att han inte längre är ledaren, eller när alla klienter inser att ledaren har ändrats och börjar skriva till den nya ledaren - beroende på vad som händer först. I alla fall kommer vissa meddelanden att gå förlorade, men bara med acks=1.

Det finns en annan variant av detta scenario där anhängarna, precis innan nätverket splittrades, hamnade på efterkälken och ledaren komprimerade ISR till bara sig själv. Den blir sedan isolerad på grund av förlust av anslutning. En ny ledare väljs, men den ursprungliga ledaren fortsätter att ta emot bidrag, till och med acks=alla, eftersom det inte finns någon annan i ISR ​​förutom han. Dessa poster kommer att gå förlorade när nätverket återställs. Det enda sättet att undvika detta alternativ är min.insync.replicas = 2.

Scenario 7: Kafka Controller Node kan inte se en annan Kafka Node

I allmänhet, när anslutningen till en Kafka-nod har förlorats, kommer styrenheten inte att kunna överföra någon information om ledareändring till den. I värsta fall kommer detta att leda till en kortsiktig logisk separation, som i scenario 6. Oftare än inte kommer mäklaren helt enkelt inte att bli en kandidat för ledarskap om det senare misslyckas.

Scenario 8: Kafka-kontrollern ser inte Zookeeper

Zookeeper kommer inte att ta emot en ping från den fallna kontrollern och kommer att välja en ny Kafka-nod som kontrollant. Den ursprungliga styrenheten kan fortsätta att presentera sig själv som sådan, men den tar inte emot aviseringar från Zookeeper, så den kommer inte att ha några uppgifter att utföra. När nätverket är återställt kommer han att inse att han inte längre är en kontrollant, utan har blivit en vanlig Kafka-nod.

Slutsatser från scenarierna

Vi ser att förlusten av följaruppkoppling inte resulterar i meddelandeförlust, utan helt enkelt tillfälligt minskar redundansen tills nätverket återställs. Detta kan naturligtvis leda till dataförlust om en eller flera noder går förlorade.

Om ledaren blir separerad från Zookeeper på grund av förlust av anslutning, kan detta leda till att meddelanden går förlorade från acks=1. Brist på kommunikation med Zookeeper orsakar en kort logisk splittring med de två ledarna. Detta problem löses av parametern acks=alla.

Parameter min.insync.repliker i två eller flera repliker ger ytterligare garantier för att sådana kortsiktiga scenarier inte kommer att resultera i förlorade meddelanden som i scenario 6.

Sammanfattning av förlorade meddelanden

Låt oss lista alla sätt du kan förlora data i Kafka:

  • Alla ledarfel om meddelanden har bekräftats med hjälp av acks=1
  • Varje oren övergång av ledarskap, det vill säga till en anhängare utanför ISR, även med acks=alla
  • Isolerar ledaren från Zookeeper om meddelanden bekräftades med hjälp av acks=1
  • Fullständig isolering av ledaren som redan har krympt ISR-gruppen till sig själv. Alla meddelanden kommer att gå förlorade, till och med acks=alla. Detta är bara sant om min.insync.replicas=1.
  • Samtidiga fel på alla partitionsnoder. Eftersom meddelanden kvitteras från minnet kanske vissa ännu inte har skrivits till disken. Efter omstart av servrarna kan vissa meddelanden saknas.

Orena ledarskapsövergångar kan undvikas genom att antingen förbjuda dem eller säkerställa minst två uppsägningar. Den mest hållbara konfigurationen är en kombination acks=alla и min.insync.repliker över 1.

Direkt jämförelse av tillförlitligheten hos RabbitMQ och Kafka

För att säkerställa tillförlitlighet och hög tillgänglighet implementerar båda plattformarna ett primärt och sekundärt replikeringssystem. RabbitMQ har dock en akilleshäl. När du återansluter efter ett fel, kasserar noder sina data och synkroniseringen blockeras. Denna dubbla smäll ifrågasätter livslängden för stora köer i RabbitMQ. Du måste acceptera antingen minskad redundans eller långa blockeringstider. Att minska redundansen ökar risken för massiv dataförlust. Men om köerna är små, kan korta perioder av otillgänglighet (några sekunder) för redundansens skull hanteras med upprepade anslutningsförsök.

Kafka har inte det här problemet. Den förkastar data endast från punkten av divergens mellan ledaren och följaren. All delad data sparas. Dessutom blockerar inte replikering systemet. Ledaren fortsätter att acceptera inlägg medan den nya följaren kommer ikapp, så för devops blir det en trivial uppgift att gå med eller gå med i klustret igen. Naturligtvis finns det fortfarande problem som nätverksbandbredd under replikering. Om du lägger till flera följare samtidigt kan du stöta på en bandbreddsbegränsning.

RabbitMQ är överlägsen Kafka i tillförlitlighet när flera servrar i ett kluster misslyckas samtidigt. Som vi redan har sagt, skickar RabbitMQ en bekräftelse till utgivaren först efter att meddelandet har skrivits till disken av mastern och alla speglar. Men detta lägger till ytterligare latens av två skäl:

  • fsync med några hundra millisekunder
  • Misslyckandet i spegeln kan bara märkas efter att livslängden för paketen som kontrollerar tillgängligheten för varje nod (nettick) har löpt ut. Om spegeln saktar ner eller faller, lägger detta till en fördröjning.

Kafkas insats är att om ett meddelande lagras över flera noder, kan det kvittera meddelanden så snart de träffar minnet. På grund av detta finns det en risk att förlora meddelanden av alla slag (även acks=alla, min.insync.replicas=2) vid samtidig fel.

Sammantaget uppvisar Kafka bättre mjukvaruprestanda och är designad från grunden för kluster. Antalet följare kan utökas till 11 vid behov för tillförlitligheten. Replikeringsfaktor 5 och minsta antal repliker i synkronisering min.insync.replicas=3 kommer att göra meddelandeförlust till en mycket sällsynt händelse. Om din infrastruktur kan stödja detta replikeringsförhållande och redundansnivå, kan du välja det här alternativet.

RabbitMQ-klustring är bra för små köer. Men även små köer kan växa snabbt när det är tung trafik. När köerna väl blir stora måste du göra svåra val mellan tillgänglighet och tillförlitlighet. RabbitMQ-klustring är bäst lämpat för icke-typiska situationer där fördelarna med RabbitMQs flexibilitet överväger eventuella nackdelar med dess klustring.

Ett motgift mot RabbitMQs sårbarhet för stora köer är att dela upp dem i många mindre köer. Om du inte kräver fullständig beställning av hela kön, utan bara relevanta meddelanden (till exempel meddelanden från en specifik kund), eller inte beställer något alls, är det här alternativet acceptabelt: titta på mitt projekt Rebalanserare att dela upp kön (projektet är fortfarande i ett tidigt skede).

Slutligen, glöm inte ett antal buggar i klustrings- och replikeringsmekanismerna för både RabbitMQ och Kafka. Med tiden har systemen blivit mer mogna och stabila, men inget meddelande kommer någonsin att vara 100% säkert från förlust! Dessutom inträffar storskaliga olyckor i datacenter!

Om jag har missat något, gjort ett misstag eller om du inte håller med om någon av punkterna får du gärna skriva en kommentar eller kontakta mig.

Jag får ofta frågan: "Vad ska jag välja, Kafka eller RabbitMQ?", "Vilken plattform är bättre?". Sanningen är att det verkligen beror på din situation, nuvarande erfarenhet etc. Jag är tveksam till att ge min åsikt eftersom det skulle vara för mycket av en överenkling att rekommendera en plattform för alla användningsfall och eventuella begränsningar. Jag skrev den här artikelserien så att du kan bilda dig din egen uppfattning.

Jag vill säga att båda systemen är ledande inom detta område. Jag kan vara lite partisk eftersom jag från min erfarenhet av projekt tenderar att värdesätta saker som garanterad meddelandeordning och tillförlitlighet.

Jag ser andra teknologier som saknar denna tillförlitlighet och garanterade ordning, sedan tittar jag på RabbitMQ och Kafka och inser det otroliga värdet av båda dessa system.

Källa: will.com

Lägg en kommentar