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.