Topp 6 kösystem för backend-utvecklare

Letar du efter ett kösystem? Eller kanske du letar efter en bättre? Här är all information du behöver!

Kösystem är den bäst bevarade hemligheten för utveckling av backend.

Utan att försöka skriva ut en dikt till beröm av kösystem, skulle jag säga att en junior backend-utvecklare blir en backend-utvecklare på mellannivå efter att han lärt sig att integrera köer i systemet. Köer förbättrar kundupplevelsen (vi får se hur), minskar komplexiteten och förbättrar tillförlitligheten i ett system.

Visst, för mycket enkla webbappar med nästan noll trafik och broschyrwebbplatser kan köer vara övergripande (eller till och med omöjliga att installera om du använder en typisk delad värdmiljö), men icke-triviala appar kommer alla att tjäna på att köa system och stora appar är omöjliga utan att köa.

Innan vi börjar, en ansvarsfriskrivning: om du redan är bekväm med kösystem och vill jämföra de olika alternativen, kommer de kommande inledande avsnitten att inducera stor sömn. 🙂 Så hoppa gärna fram. De inledande avsnitten är avsedda för dig som bara har en dunkel idé om kösystem eller bara hört namnet i förbigående.

Vad är ett kösystem?

Låt oss börja med att förstå vad en kö är.

En kö är en datastruktur inom datavetenskap som efterliknar, ja, de verkliga köerna vi ser omkring oss. Om du till exempel går till en biljettdisk kommer du att märka att du måste stå i slutet av kön, medan personen i början av kön får biljetten först. Detta är vad vi också kallar ”först till kvarn”-fenomenet. Inom datavetenskap är det möjligt att skriva program som lagrar sina uppgifter så här i en kö, och bearbetar dem en efter en på samma princip som först till kvarn.

Observera att kön inte gör någon faktisk bearbetning själv. Det är bara tillfällig förvaring av olika slag där uppgifter väntar tills de blir upplockade av något. Om allt detta låter lite för abstrakt, oroa dig inte. Det är ett abstrakt koncept, men vi kommer att se tydliga exempel i nästa avsnitt. 🙂

Varför behöver du kösystem?

Utan att gå in på en mycket lång beskrivning, skulle jag säga att det huvudsakliga behovet av kösystem är på grund av bakgrundsbearbetning, parallell körning och återställning från fel. Låt oss titta på dessa med hjälp av exempel:

Bakgrundsbearbetning

Anta att du kör en marknadsföringskampanj för e-handel där tiden är avgörande, och att din applikation är byggd så att den avfyrar ett bekräftelsemail precis innan kunden slutför betalningen och visas med ”tack”-sidan. Om e-postservern du ansluter till är nere kommer webbsidan bara att dö, vilket bryter användarupplevelsen.

Föreställ dig det stora antalet supportförfrågningar du skulle få! I det här fallet är det bättre att skicka denna e-postsändningsuppgift till en jobbkö och visa kunden framgångssidan.

Parallellt utförande

Många utvecklare, särskilt de som oftast kodar enklare appar med låg trafik, har för vana att använda cron-jobb för bakgrundsbearbetning. Detta är bra tills storleken på inmatningen blir så stor att den inte kan rensas. Anta till exempel att du har ett cron-jobb som sammanställer analysrapporter och e-postar dem till användarna och att ditt system kan behandla 100 rapporter per minut.

Så fort din app växer och börjar få mer än 100 förfrågningar per minut i snitt kommer den att börja hamna på efterkälken mer och mer och kommer aldrig att kunna slutföra alla jobb.

I ett kösystem kan denna situation undvikas genom att sätta upp flera arbetare, som var och en kan välja ett jobb (som innehåller 100 rapporter som ska göras var) och arbeta parallellt för att avsluta uppgiften mycket, mycket tidigare.

Återhämtning från misslyckande

Vi tänker i allmänhet inte på misslyckande som webbutvecklare. Vi tar det för givet att våra servrar och de API:er vi använder alltid kommer att vara online. Men verkligheten är en annan – nätverksavbrott är alltför vanliga, och de utmärkta API:er du litar på kan vara nere på grund av infrastrukturproblem (innan du säger ”inte jag!”, glöm inte massiva Amazon S3-avbrott). Så, om vi går tillbaka till rapporteringsexemplet, om en del av din rapportgenerering kräver att du ansluter till betalnings-API och den anslutningen är nere i 2 minuter, vad händer med de 200 rapporterna som misslyckades?

Kösystem innebär dock betydande omkostnader. Inlärningskurvan är ganska brant när du kliver in i en helt ny domän, komplexiteten i din applikation och implementering ökar och köade jobb kan inte alltid kontrolleras med 100 % precision. Som sagt, det finns situationer när det inte är möjligt att bygga en applikation utan köer.

Med det ur vägen, låt oss ta en titt på några av de vanliga alternativen bland köande backends/system idag.

Redis

Redis är känt som ett nyckel-värdelager som bara lagrar, uppdaterar och hämtar datasträngar utan kunskap om datastrukturen. Även om det kan ha varit sant tidigare, har Redis idag effektiva och mycket användbara datastrukturer som listor, sorterade uppsättningar och till och med ett Pub-Sub-system, vilket gör det mycket önskvärt för köimplementeringar.

Fördelarna med Redis är:

  • Helt i minnet databas, vilket resulterar i snabbare läsning/skrivning.
  • Mycket effektiv: Kan enkelt stödja mer än 100 000 läs-/skrivoperationer per sekund.
  • Mycket flexibelt uthållighetssystem. Du kan antingen välja maximal prestanda till priset av eventuell dataförlust i händelse av fel eller ställa in i helt konservativt läge för att offra prestanda för konsekvens.
  • Kluster stödda ur lådan

Observera att Redis inte har några meddelanden/köer/återställningsabstraktioner, så du behöver antingen använda ett paket eller bygga ett lättviktigt system själv. Ett exempel är att Redis är standardköbackend för Laravel PHP-ramverket, där en schemaläggare har implementerats av ramverksförfattarna.

Att lära sig Redis är lätt.

RabbitMQ

Det finns några subtila skillnader mellan Redis och RabbitMQså låt oss få dem ur vägen först.

Först och främst har RabbitMQ en mer specialiserad, väldefinierad roll, och därför byggd för att återspegla det – meddelanden. Med andra ord är dess sweet spot att fungera som en förmedlare mellan två system, vilket inte är fallet för Redis, som fungerar som en databas. Som ett resultat tillhandahåller RabbitMQ ytterligare några faciliteter som saknas i Redis: meddelandedirigering, återförsök, lastdistribution, etc.

Om du tänker på det, kan uppgiftsköer också ses som ett meddelandesystem, där schemaläggaren, arbetarna och ”inlämnarna” av jobb kan ses som enheter som deltar i meddelandeöverföring.

RabbitMQ har följande fördelar:

  • Bättre abstraktioner för att skicka meddelanden, vilket minskar arbetet på applikationsnivå om meddelandeöverföring är vad du behöver.
  • Mer motståndskraftig mot strömavbrott och avbrott (än Redis, åtminstone som standard).
  • Kluster- och federationsstöd för distribuerade distributioner.
  • Användbara verktyg för att hantera och övervaka dina distributioner.
  • Stöd för praktiskt taget alla icke-triviala programmeringsspråk som finns.
  • Implementering med ditt valfria verktyg (Docker, Chef, Puppet, etc.).

När ska man använda RabbitMQ? Jag skulle säga att det är ett utmärkt val när du vet att du behöver använda asynkron meddelandeöverföring men inte är redo att ta itu med den höga komplexiteten hos några av de andra köalternativen på den här listan (se nedan).

ActiveMQ

Om du är intresserad av företagsområdet (eller bygger en mycket distribuerad och storskalig app) och du inte vill behöva uppfinna hjulet på nytt hela tiden (och göra misstag längs vägen), ActiveMQ är värt en titt.

Här är där ActiveMQ utmärker sig:

  • Det är implementerat i Java och har så snygg Java-integration (följer JMS-standarden).
  • Flera protokoll som stöds: AMQP, MQTT, STOMP, OpenWire, etc.
  • Hanterar säkerhet, routing, meddelandeförfall, analyser etc. direkt.
  • Inbakat stöd för populära distribuerade meddelandemönster, vilket sparar tid och kostsamma misstag.

Därmed inte sagt att ActiveMQ endast är tillgängligt för Java. Den har klienter för Python, C/C++, Node, .Net och andra ekosystem, så det bör inte finnas några farhågor för en eventuell kollaps i framtiden. Dessutom är ActiveMQ byggt på helt öppna standarder och att bygga dina egna lättviktsklienter borde vara enkelt.

Allt som sagt och gjort, var medveten om att ActiveMQ bara är en mäklare och inte inkluderar en backend. Du måste fortfarande använda en av de stödda backends för att lagra meddelanden. Jag inkluderade det här eftersom det inte är knutet till ett visst programmeringsspråk (som andra populära lösningar som Celery, Sidekiq, etc.)

Amazon MQ

Amazon MQ förtjänar ett snabbt men viktigt omnämnande här. Om du tror att ActiveMQ är den idealiska lösningen för dina behov men inte vill ta itu med att bygga och underhålla infrastrukturen själv, erbjuder Amazon MQ en hanterad tjänst för att göra det. Den stöder alla protokoll som ActiveMQ gör – det finns ingen skillnad i funktioner alls – eftersom den använder ActiveMQ själv under ytan.

Fördelen är att det är en hanterad tjänst, så du behöver inte oroa dig för något annat än att använda den. Det är ännu mer meningsfullt för de implementeringar som är på AWS, eftersom du kan dra nytta av andra tjänster och erbjudanden direkt från din implementering (snabbare dataöverföringar, till exempel).

Amazon SQS

Vi kan väl inte förvänta oss att Amazon ska sitta tyst när det gäller kritiska infrastrukturdelar? 🙂

Och så har vi Amazon SQS, som är en helt värd, enkel kötjänst (bokstavligen) av den välkända jätten AWS. Än en gång, subtila skillnader är viktiga, så observera att SQS inte har konceptet att skicka meddelanden. Precis som Redis är det en enkel backend för att acceptera och distribuera jobb i köer.

Så när skulle du vilja använda Amazon SQS? Här är några anledningar:

  • Du är ett AWS-fan och kommer inte att röra något annat (ärligt talat, det finns många sådana där ute, och jag tror att det inte är något fel med det).
  • Du behöver en värdlösning så se till att felfrekvensen är noll och att inga jobb går förlorade.
  • Du vill inte bygga ut ett kluster och måste övervaka det själv. Eller ännu värre, måste bygga övervakningsverktyg när du kan använda den tiden för att göra produktiv utveckling.
  • Du har redan betydande investeringar i AWS-plattformen och att hålla dig låst är affärsmässigt vettigt.
  • Du vill ha ett fokuserat, enkelt kösystem utan något av fluffen som är förknippad med meddelandeöverföring, protokoll och annat.

Allt som allt är Amazon SQS ett solidt val för alla som vill införliva jobbköer i sitt system och inte behöver oroa sig för att installera/övervaka saker själva.

Bönstjälkd

Bönstjälkd har funnits länge och är en stridstestad, snabb, enkel backend för jobbköer. Det finns några egenskaper hos Beanstalkd som gör att den skiljer sig avsevärt från Redis:

  • Det är strikt ett jobbkösystem och inget annat. Du skjuter jobb till det, som senare dras av jobbarbetare. Så om din ansökan ens har ett litet behov av att skicka meddelanden, vill du undvika Beanstalkd.
  • Det finns inga avancerade datastrukturer som uppsättningar, prioritetsköer etc.
  • Beanstalkd är vad som kallas en First In, First Out (FIFO)-kö. Det finns inget sätt att ordna jobb efter prioritet.
  • Det finns inga alternativ för klustring.

Allt detta säger Beanstalkd ger ett smidigt och snabbt kösystem för enkla projekt som lever på en enda server. För många är det snabbare och stabilare än Redis. Så om du har frågor med Redis som du bara inte kan lösa oavsett vad, och dina behov är enkla, är Beanstalkd värt ett försök.

Slutsats

Om du har läst så här långt (eller nått hit skumläsning 😉 ), är chansen ganska stor att du är intresserad av kösystem eller behöver ett. Om så är fallet kommer listan på den här sidan att tjäna dig väl, om du inte letar efter ett språk-/ramspecifikt kösystem.

Jag önskar att jag kunde berätta att köandet är enkelt och 100 % tillförlitligt, men det är det inte. Det är rörigt, och eftersom det hela är i bakgrunden och sker väldigt snabbt (misstag kan gå obemärkta förbi och bli väldigt kostsamma). Ändå är köer mycket nödvändiga bortom en punkt, och du kommer att upptäcka att de är ett kraftfullt vapen (kanske till och med det mest kraftfulla) i din arsenal. Lycka till! 🙂