208 208.fi

Hög tillgänglighet genom en distribuerad arkitektur

Några praktiska begränsningar för tjänsteduplicering


Hög tillgänglighet innebär att tjänsten sannolikt är tillgänglig. När tjänsten distribueras till flera oberoende enheter ska en enda enhet besvara färre förfrågningar. Detta ger inte bara bättre prestanda eller svarstid, utan också bättre feltolerans. Om en av våra namnservrar skulle sakta ner eller blockeras skulle tjänsten fortsätta tack vare en annan namnserver.

I teorin spelar orsaken till enhetens fel egentligen ingen roll. Den mest sannolika störningen av våra namnservrar är förmodligen regelbunden uppdatering av tjänstecontainrar och innehåll, vilket inaktiverar en server åt gången under en kort period. Eftersom funktionaliteten hos den uppdaterade tjänsten kontrolleras innan den nästa enhet uppdateras, kan maximalt en enhet förstöras. Om det behövs, kan den kan återställas till situationen före uppdateringen. Under den tiden håller de andra servrarna tjänsten tillgänglig. För oss sker allt detta automatiskt i vårt GitLab-baserade ERP-system.

Tillgänglighets matematik

Tillgängligheten av en tjänst kan beskrivas som sannolikheten att tjänsten kommer att vara tillgänglig vid en godtycklig tidpunkt. Om tjänsten dupliceras på n enheter som fallerar oberoende av varandra, så att sannolikheten för att enheten fallerar vid en viss tidpunkt är p, är sannolikheten att hela tjänsten misslyckas, det vill säga att ingen enhet svarar, pⁿ.

Till exempel, när man siktar på 99,9999 % tillgänglighet, dvs. pⁿ=10⁻⁶, kan tjänsten vara otillgängligt i maximalt 86,4 millisekunder per dygn (86 400 sekunder).

Med ett fördubblat system uppnås detta tillgänglighetsmål när sannolikheten för fel i en enhet är p=10⁻³, det vill säga enheten är otillgänglig i maximalt 86,4 sekunder per dag. Detta är tillräckligt för målet om det värsta felet är en störning i nätverksanslutningen som varar mindre än en minut eller en planerad uppdatering högst en gång per dag.

I ett kluster av tre system uppnås tillgänglighetsmålet när p=10⁻², det vill säga avbrott för en enskild enhet oberoende av andra, varar högst 14 minuter och 24 sekunder per dag.

Hur är det med större fel som tar timmar eller dagar att åtgärda? Om vi antar att de är så osannolika att de bara kan inträffa en eller två samtidigt, kan ett motsvarande antal oberoende reservenheter helt enkelt läggas till.

Större fel, såsom förlust av ryggradsnätverksanslutningen eller en brand i ett datacenter, åtgärdas genom att en ersättningsserver från ett annat datacenter rullas ut, vilket kräver mänskligt arbete. Vid ett sådant fel är tillgängligheten för en enskild enhet högst i storleksordningen p=10⁻¹ (2,4 timmar per dag) och tillgänglighetsmålet skulle faktiskt kräva installation av minst n=6 servrar i oberoende datacenter.

Enkel decentralisering med centraliserad kontroll

En tjänst är lätt att duplicera när den baseras på innehåll som sällan ändras. Till exempel uppdateras programvaran och certifikaten för våra namnservrar var tredje dag. Dessutom kan innehållet ändras vid behov, vanligtvis mer sällan.

På samma sätt kan man duplicera en blockeringstjänst för certifikat eller en webbserver som tillhandahåller statiskt innehåll. Men hur är det med tjänster vars innehåll ändras under användning?

Replikering av förändringar under användning

I e-posttjänsten ändras innehållet (användarnas brevlådor) under användning. SMTP-servrar är dock baserade på meddelandeköer, som i princip är utformade för att vara redundanta. Inkommande meddelanden kan dupliceras till flera servrar redan innan avsändaren tillåts stänga SMTP-anslutningen. Varje meddelande har en unik identifierare Message-Id. Vanligtvis är brevlådor personliga, och en enda brevlåda redigeras inte samtidigt på flera apparat. E-postbrevlådor som dupliceras till olika servrar skulle kunna hållas uppdaterade med hjälp av lås och loggpostar, dvs. genom att implementera ett enkelt distribuerat databassystem. Administration är ganska enkel om ändringar i en enda brevlåda tillåts från högst en server eller terminalenhet i taget.

I en onlinemarknadsplats eller bokningssystem kan användare samtidigt titta på och redigera det delade innehållet. Om det finns ett begränsat antal virala prylar, hobbypass eller platser tillgängliga, bör användarna kunna se den aktuella situationen och kunna reservera sitt val tills transaktionen har bekräftats eller avbrutits. Hjärnan i en sådan applikation är ofta databassystemet som hanterar transaktioner och låsning.

En applikation som är byggd på en centraliserad databas kan omvandlas till en distribuerad genom att ta i bruk ett distribuerat databashanteringssystem. En välskriven applikation är förberedd för felsituationer som leder till transaktionsrullning, såsom dödlägen eller låsväntetider.

Distribuerade system med flera skrivbara noder

Ett centraliserat system, där alla ändringar görs i ett enda huvudsystem som duplicerar ändringarna till reservsystem som endast hanterar läsförfrågningar, är relativt enkelt att implementera och underhålla.

Det är dock komplext att implementera en pålitlig failover-mekanism som främjar ett reservsystem till en primär server. Vad händer om primärservern förblir delvis nåbar och vissa användare fortsätter använda den medan andra har migrerat till den nya primärservern?

Ett distribuerat system får aldrig hamna i en situation med klyvade härnan där användare fortsätter använda separata primära servrar och antar att alla delar samma syn. Om ett distribuerat databassystem förväntar sig att varje operation ska bekräftas av alla servrar, kommer de långsammaste anslutningarna att avgöra hastigheten. God prestanda kräver buffring av ändringar och majoritetsbeslutsfattande, samt snabb respons på störningar.

Ett verkligt distribuerat system, där klustrets tjänstenoder snabbt kan byta roller, kräver en distribuerad algoritm eller protokoll för ledarval, en effektiv låshantering och en återställningsmekanism. När en tidigare ledare återfår anslutningen till de andra noderna och upptäcker att den har degraderats, måste den antingen rulla tillbaka sina lokala förändringar som andra saknar, eller försöka replikera dem efter att ha replikerat de förändringar som utförts i klustret. Ledarbyten kan vara frekventa, och kommunikationsfel kan uppstå under valet.

I ett distribuerat system kan händelser ordnas på mycket många olika sätt, eller faktiskt delvis ordnas, eftersom de olika delarna av systemet som har egna klockor kan observera olika ordning av händelser. Systemuppgraderingar blir också mer komplexa, eftersom vissa noder under en uppgradering kör en annan mjukvaruversion.

Att utveckla robusta distribuerade algoritmer kräver användning av formella metoder, såsom korrekthetsbevis och verifiering via modellkontroll och nåbarhetsanalys. För att hantera tillståndsrymdexplosionen måste en lämplig abstraktionsnivå hittas. En av oss har berört något av detta i en doktorsavhandling.

Just nu anser vi att ansträngningen att implementera någon form av replikering i vårt GitLab-ERP-system är större än den möjliga nyttan. Vi lägger hellre lite mer manuellt arbete ifall systemet fallerar än riskerar att en automatiserad failover-mekanism misslyckas. Det är lättare att hantera störningar när världen står still. Den synliga världen slutar självklart inte, våra offentlig tillgängliga tjänster körs ju i helt andra miljöer i enlighet med vår flerlagriga datasäkerhetsarkitektur.

För att förutsäga och förhindra fel på en enskild enhet använder vi automatiska tillförlitlighetsprov som tar fram förslag på åtgärder.

CC BY 4.0