Denna artikel leder först till vilka problem meddelandemiddleware vanligtvis behöver lösa, vilka svårigheter som kommer att uppstå vid lösningen av dessa problem, om Apache RocketMQ kan lösas som en högpresterande, högkapacitets distribuerad meddelandemiddleware öppen källkod av Alibaba, och hur dessa problem definieras i specifikationen. Denna artikel kommer sedan att introducera arkitekturdesignen för RocketMQ för att ge läsarna en snabb förståelse för RocketMQ. 1. Vilka problem behöver meddelande-middleware lösa? Publicera/Prenumerera är den mest grundläggande funktionen i meddelandemellanvara och är också relativ till traditionell RPC-kommunikation. Jag kommer inte gå in på detaljer här. Prioriteten som beskrivs i Message Priority-specifikationen avser en meddelandekö, varje meddelande har en annan prioritet, vanligtvis beskriven med heltal, meddelandet med hög prioritet levereras först, om meddelandet är helt i en minneskö kan det sorteras efter prioriteten före leverans, så att den högsta prioriteten levereras först. Eftersom alla meddelanden i RocketMQ är persistent, om de sorteras efter prioritet, kommer overheaden att vara mycket stor, så RocketMQ stöder inte specifikt meddelandeprioritet, men kan implementera liknande funktioner i en lösning, det vill säga konfigurera en kö med hög prioritet och en kö med normal prioritet, och skicka olika prioriteringar till olika köer. För prioriterade frågor kan de sammanfattas i två kategorier:
- Så länge prioriteten uppnås är det inte en prioritet i strikt mening, och prioriteten delas vanligtvis in i hög, medel, låg eller flera fler nivåer. Varje prioritet kan representeras av ett annat ämne, och när man skickar ett meddelande, ange olika ämnen som representerar prioriteten, vilket kan lösa de flesta prioriteringsproblemen men kompromissa med affärsprioriteringarnas noggrannhet.
- Strikt prioritet, prioritet uttrycks som ett heltal, såsom 0 ~ 65535, denna typ av prioritetsproblem är generellt inte lämplig att lösa med olika ämnen. Om du vill att MQ ska lösa detta problem kommer det att ha en mycket stor påverkan på MQ:s prestanda. Här är en poäng för att säkerställa att företaget verkligen behöver denna strikta prioritering, och om prioriteringarna komprimeras till få, hur stor påverkan kommer det att ha på verksamheten?
Meddelandeordning avser en typ av meddelande som kan konsumeras i den ordning det skickas. Till exempel genererar en order tre meddelanden, nämligen orderskapande, orderbetalning och orderslutförande. När man konsumerar är det meningsfullt att konsumera i denna ordning. Men samtidigt kan beställningar konsumeras parallellt. RocketMQ kan strikt säkerställa att meddelandena är ordnade. Message FilterBroker Meddelandefiltrering I Broker har filtrering enligt konsumentens behov fördelen att minska överföringen av onödiga meddelanden till konsumenten. Nackdelen är att det ökar bördan för mäklaren och är relativt komplext att genomföra. 1. Taobao Notify stöder en mängd olika filtreringsmetoder, inklusive direkt filtrering efter meddelandetyp och flexibel syntaxuttrycksfiltrering, vilket kan möta nästan de mest krävande filtreringsbehoven. 2. Taobao RocketMQ stöder filtrering efter enkel meddelandetagg, samt meddelandehuvud och brödtext. 3. Flexibel syntaxuttrycksfiltrering stöds också i CORBA-notifikationsspecifikationen. Konsumentsidans meddelandefiltrering Denna filtrering kan anpassas helt av applikationen, men nackdelen är att många värdelösa meddelanden skickas till konsumenten. Det finns flera vanliga persistensmetoder som används av meddelandepersistens:
- Persistera i en databas, som Mysql.
- Persistera till KV-lagring, såsom levelDB, Berkeley DB och andra KV-lagringssystem.
- Persistens i form av filpostar, såsom Kafka, RocketMQ
- Skapa en bevarad bild av minnesdatan, såsom beanstalkd, VisiNotify
- (1), (2) och (3) alla tre persistensmetoder har förmågan att utöka minnesköbufferten, och (4) är bara en minnesavbildning, som fortfarande kan återställa data från det föregående minnet efter att brokern lagt på och startat om.
JMS- och CORBA-notifikationsspecifikationerna specificerar inte uttryckligen hur man ska upprätthållas, men prestandan hos persistensdelen avgör direkt prestandan för hela meddelandemittvaran. RocketMQ utnyttjar fullt ut Linux filsystemets minnescache för att förbättra prestandan. Det finns flera situationer där meddelandets tillförlitlighet påverkar meddelandets tillförlitlighet:
- Mäklaren stänger normalt
- Mäklarkraschen
- OS-krasch
- Maskinen förlorar ström, men strömförsörjningen kan återställas omedelbart.
- Maskinen startar inte (den kan skadas på viktiga enheter som CPU, moderkort, minne, etc.)
- Skada på diskenheten.
(1), (2), (3) och (4) är alla situationer där hårdvaruresurser kan återställas omedelbart, och RocketMQ kan säkerställa att meddelanden inte går förlorade eller att en liten mängd data går förlorad (beroende på om flashningsmetoden är synkron eller asynkron). (5) (6) Det är en enda felpunkt och kan inte återställas, när det väl inträffar förloras alla meddelanden på denna enda punkt. I båda fallen säkerställer RocketMQ att 99 % av meddelandena inte går förlorade genom asynkron replikering, men det finns fortfarande mycket få meddelanden som kan gå förlorade. Synkron dubbelskrivningsteknik kan helt undvika enskilda punkter, vilket oundvikligen påverkar prestandan, vilket gör den lämplig för situationer med extremt höga krav på meddelandens tillförlitlighet, såsom Money-relaterade applikationer. RocketMQ stöder synkron dubbelskrivning från och med version 3.0. Meddelanden med låg latens kan nå konsumenten omedelbart efter att meddelandet nått mäklaren utan att samla på sig meddelanden. RocketMQ använder en lång polling pull-metod för att säkerställa att meddelandet är mycket realtidsbaserat och att realtidsmeddelandet inte är lägre än push-meddelandet. Minst en gång innebär att varje meddelande måste levereras en gång. RocketMQ Consumer hämtar först meddelandet till det lokala området och returnerar sedan acken till servern efter att förbrukningen är klar. Exakt bara en gång- Sändningssteget tillåter inte att dubbla meddelanden skickas.
- I steget Konsumera meddelande får inte dubbletter konsumeras.
Endast när ovanstående två villkor är uppfyllda kan meddelandet betraktas som "Exakt Endast En gång", och för att uppnå ovanstående två punkter kommer enorm overhead oundvikligen att genereras i den distribuerade systemmiljön. Därför garanterar RocketMQ inte denna funktion för att uppnå hög prestanda, och kräver deduplicering i verksamheten, vilket innebär att konsumentmeddelanden måste vara idempotenta. Även om RocketMQ inte strikt kan garantera icke-duplicering, förekommer det under normala omständigheter sällan upprepade sändningar och konsumtion, endast nätverksavvikelser, konsumentstart och -stopp samt andra onormala situationer såsom meddelandeduplicering. Den grundläggande orsaken till detta problem är att det finns osäkerhet i nätverkssamtal, det vill säga det tredje tillståndet av varken framgång eller misslyckande, så problemet med meddelandeupprepning uppstår. Vad ska jag göra om mäklarens buffert är full? Mäklarens buffert syftar vanligtvis på minnesbuffertstorleken för en kö i mäklaren, som vanligtvis är begränsad i storlek, tänk om bufferten är full? Så här hanteras det i CORBA:s notifikationsspecifikation:
- RejectNewEvents avvisar det nya meddelandet och returnerar felkoden RejectNewEvents till producenten.
- Kasta befintliga meddelanden enligt en specifik policy
- AnyOrder – Alla händelser kan kasseras vid överflöd. Detta är standardinställningen för denna egenskap.
- FifoOrder – Den första händelsen som tas emot är den första som kastas.
- LifoOrder – Den sista händelsen som tas emot är den första som kastas.
- PriorityOrder – Händelser bör kasseras i prioriterad ordning, så att händelser med lägre prioritet kasseras före händelser med högre prioritet.
- DeadlineOrder – Händelser bör först kastas i ordningen efter kortaste utgångsdatum.
RocketMQ har inte konceptet minnesbuffert, och köerna i RocketMQ är persistenta diskar, och datan rensas regelbundet. För lösningen på detta problem har RocketMQ en mycket betydande skillnad från andra MQ:er, RocketMQ:s minnesbuffert är abstraherad till en oändlig kö, oavsett hur mycket data som kommer in kan den installeras, denna oändlighet är presump, mäklaren raderar regelbundet utgången data, till exempel sparar mäklaren bara meddelanden i tre dagar, och även om bufferten är oändlig, raderas data från tre dagar sedan från slutet av kön. Retrospektiv konsumtion avser det budskap som konsumenten framgångsrikt har konsumerat, och meddelandet behöver återkonsumeras på grund av företagets efterfrågan. Till exempel, på grund av fel i konsumentsystemet, måste data från för 1 timme sedan återkonsumeras efter återställning, och sedan bör mäklaren tillhandahålla en mekanism för att återställa konsumtionsprogressionen enligt tidsdimensionen. RocketMQ stöder retrospektiv konsumtion baserad på tid, med en tidsdimension som är noggrann med millisekunder, och som kan backas framåt eller bakåt. Huvudfunktionen för meddelandestackningsmiddleware är asynkron decoupling, och en annan viktig funktion är att blockera dataöverflödstoppen i front-end och säkerställa stabiliteten i backend-systemet, vilket kräver att meddelandemiddleware har en viss förmåga att stacka meddelanden, och message heap integrerar följande två situationer:
- Meddelanden staplas i minnesbuffertar, och när de överskrider minnesbufferten kan meddelanden släppas enligt en viss dropppolicy, som beskrivs i CORBA Notification-specifikationen. Den är lämplig för tjänster som kan tolerera kasserande meddelanden, i detta fall ligger ackumuleringskapaciteten för meddelanden främst i storleken på minnesbufferten, och prestandaförsämringen blir inte alltför stor efter att meddelandet staplats, eftersom mängden data i minnet har en begränsad påverkan på åtkomstmöjligheten som ges till omvärlden.
- Meddelanden staplas i persistenta lagringssystem såsom databas, KV-lagring eller filpostform. När meddelanden inte kan träffas i minnescachen är det oundvikligt att komma åt disken, vilket genererar en stor mängd läs-IO, och genomströmningen av läs-IO avgör direkt åtkomstförmågan för meddelanden efter att de har samlats på hög i hög.
Det finns fyra huvudpunkter för att utvärdera förmågan att samla meddelanden:
- Hur många meddelanden kan staplas på hög, hur många bytes? Det vill säga meddelandets heapkapacitet.
- Efter att ett meddelande har staplats, påverkas då genomströmningen av meddelandet av staplingen?
- Kommer konsumenternas normala konsumtion att påverkas efter att budskapen hopat sig?
- När meddelandena har samlats på hög, hur stor är genomströmningen när man får tillgång till meddelanden som samlats på disken?
Distribuerade transaktioner Flera kända distribuerade transaktionsspecifikationer, såsom XA, JTA, etc. Bland dessa stöds XA-specifikationen brett av stora databasleverantörer, såsom Oracle, Mysql, etc. Bland dem används XAs TM-implementeringsledare som Oracle Tuxedo i stor utsträckning inom finans, telekommunikation och andra områden. Distribuerade transaktioner involverar tvåstegs-commit-problem, och när det gäller datalagring måste KV-lagring stödjas, eftersom det andra steget i commit-rollbacken måste ändra meddelandets tillstånd, vilket måste innebära att man hittar meddelandet enligt nyckeln. RocketMQ kringgår problemet med att hitta meddelandet enligt nyckeln i andra steget, genom att använda första steget för att skicka det förberedda meddelandet, få offsetet på meddelandet, och det andra steget för att komma åt meddelandet via offsetet och ändra tillståndet, offsetet är datans adress. RocketMQ:s transaktionsimplementeringsmetod görs inte via KV-lagring, utan via offset-metoden, som har en betydande brist, nämligen att ändring av data via offset orsakar för många smutsiga sidor i systemet, vilket kräver särskild uppmärksamhet. Schemalagda meddelanden Schemalagda meddelanden innebär att meddelanden inte kan konsumeras av konsumenter omedelbart efter att de skickats till mäklaren, och endast kan konsumeras vid en specifik tidpunkt eller efter att ha väntat på en viss tidpunkt. Om du vill stödja godtycklig tidsnoggrannhet på mäklarnivå måste du göra meddelandesortering, och om persistens är inblandad kommer meddelandesortering oundvikligen att medföra stora prestandaöverhuvud. RocketMQ stöder tidsmeddelanden, men stöder inte godtycklig tidsnoggrannhet och stöder specifika nivåer, såsom timing 5s, 10s, 1m, etc. Meddelandeförsök Efter att konsumenten misslyckats med att konsumera meddelandet, tillhandahåll en återförsöksmekanism för att få meddelandet att konsumera igen. Konsumentkonsumtionsmeddelanden kan vanligtvis betraktas i följande situationer:
- På grund av själva meddelandets orsak, såsom deserialiseringsfel, kan inte meddelandedata bearbetas (till exempel mobilräkningsladdning, mobilnumret till det aktuella meddelandet är utloggat, kan inte laddas på), etc. Detta fel kräver vanligtvis att man hoppar över detta meddelande och konsumerar andra meddelanden, och detta misslyckade meddelande är 99 % misslyckat även om konsumtionen försöker omedelbart, så det är bäst att tillhandahålla en tidsbegränsad omförsöksmekanism, det vill säga omförsök efter 10 sekunder.
- Eftersom de beroende nedströms applikationstjänsterna är otillgängliga, till exempel databasanslutningen är otillgänglig, det externa systemnätverket är oåtkomligt, etc. När detta fel uppstår, även om det aktuella misslyckade meddelandet hoppas över, kommer även andra meddelanden att konsumeras. I detta fall rekommenderas att applicera sömn 30 sekunder och konsumera nästa meddelande, vilket kan minska trycket på förmedlaren att försöka om meddelandet.
Översikt över RocketMQ Låt oss ta reda på om RocketMQ löser problemen som meddelandemiddleware nämnde ovan står inför.
Vad är RocketMQ?
Figuren ovan är en typisk modell för meddelandemellanvara som skickar och tar emot meddelanden, RocketMQ är också designad på detta sätt, kort sagt har RocketMQ följande egenskaper:
- Det är en kömodell-meddelandemellanvara med hög prestanda, hög tillförlitlighet, hög realtids- och distribuerade egenskaper.
- Producent, konsument och kö kan alla distribueras.
- Producenten skickar meddelanden till vissa köer i sin tur, kösamlingen kallas Ämne, Konsument. Om broadcast consumption konsumerar en konsumentinstans alla köer som motsvarar detta ämne, och om klusterkonsumtion konsumerar flera konsumentinstanser köinsamlingen motsvarande ämnet jämnt.
- Strikt meddelandeordning kan garanteras
- Tillhandahåller rika meddelandepull-lägen
- Effektiva horisontella abonnentskalningsmöjligheter
- Prenumerationsmekanism för meddelanden i realtid
- Hundratals miljoner meddelanden ackumulerar kapacitet
- Mindre beroende
RocketMQ:s fysiska utplaceringsstruktur
Som visas i figuren ovan har RocketMQ:s utplaceringsstruktur följande egenskaper:
- Name Server är en i princip tillståndslös nod som kan distribueras i kluster utan någon informationssynkronisering mellan noder.
- Utplaceringen av Broker är relativt komplex, Broker är uppdelad i Master och Slave, en Master kan motsvara flera Slavar, men en Slave kan bara motsvara en Master, korrespondensen mellan Master och Slave definieras genom att ange samma BrokerName, olika BrokerId, BrokerId är 0 för Master, och icke-0 betyder Slave. Masters kan också användas i flera olika grupper. Varje mäklare upprättar en lång anslutning med alla noder i Name Server-klustret och registrerar ämnesinformation till alla Name Servers med jämna mellanrum.
- Producenten upprättar en lång anslutning med en av noderna i Name Server-klustret (slumpmässigt vald), hämtar periodiskt ämnesroutningsinformation från Name Server, upprättar en lång anslutning till mastern som tillhandahåller ämnestjänsten och skickar hjärtslag till mastern med jämna mellanrum. Producer är helt tillståndslöst och kan distribueras i kluster.
- Konsumenten upprättar en lång anslutning med en av noderna i Name Server-klustret (slumpmässigt vald), hämtar regelbundet ämnesroutningsinformation från Name Server och upprättar en lång anslutning till Master och Slave som tillhandahåller ämnestjänsten, och skickar hjärtslag till Master och Slave med jämna mellanrum. Konsumenter kan prenumerera på meddelanden från både Master och Slave, och prenumerationsreglerna bestäms av Broker-konfigurationen.
RocketMQ:s logiska utplaceringsstruktur
Som visas i figuren ovan har den logiska distributionsstrukturen för RocketMQ två egenskaper: producent och konsument.
En Producer Group används för att representera en meddelandeapplikation och innehåller flera Producer-instanser, vilka kan vara flera maskiner, flera processer på en maskin eller flera Producer-objekt i en process. En producentgrupp kan skicka flera ämnesmeddelanden, och producentgruppen fungerar enligt följande:
- Identifiera en typ av producent
- Du kan fråga om det finns flera Producer-instanser i denna meddelandeapplikation via O&M-verktyget
- När man skickar ett distribuerat transaktionsmeddelande, om producenten går ner oväntat, kommer mäklaren aktivt att kalla tillbaka vilken maskin som helst i producentgruppen för att bekräfta transaktionsstatusen.
Används för att representera en konsumentmeddelandeapplikation innehåller en konsumentgrupp flera konsumentinstanser, vilka kan vara flera maskiner, flera processer eller flera konsumentobjekt i en process. Flera konsumenter i en konsumentgrupp konsumerar meddelanden på ett jämnt fördelat sätt, och om de sätts att sända förbrukar varje instans under denna konsumentgrupp hela datamängden.
RocketMQ:s datalagringsstruktur
Som visas i figuren ovan använder RocketMQ en lagringsmetod som separerar data från index. Effektivt minska förlusten av filresurser, IO-resurser och minnesresurser. Även med massiv data som Alibaba kan scenarier med hög samtidighet effektivt minska end-to-end-latens och ha starka horisontella skalningsmöjligheter.
|