Moderna distribuerade system handlar om avvägningar. Prestanda, tillförlitlighet, skalbarhet och konsekvens är inte gratis – du betalar alltid ett pris någonstans. Det är där CAP-teoremet kommer in: det är utgångspunkten för att förstå de oundvikliga kompromisserna i distribuerad design.
Varför är CAP-satsen sann? Vad förklarar det egentligen? Och viktigast av allt, räcker det? I det här inlägget kommer vi att utforska CAP-satsen, dess begränsningar, kritiken den har mött och hur nyare idéer som PACELC driver konversationen framåt. Låt oss dyka in.
Den första versionen av CAP-teoremet började som en debatt mellan ACID vs. BASE . Men med tiden utvecklades det, fick ett formellt bevis och tog examen för att bli CAP-teoremet som vi känner det idag.
CAP-satsen säger att ett distribuerat system kan uppfylla högst två av tre egenskaper samtidigt :
Denna begränsning tvingar ingenjörer att göra svåra avvägningar beroende på systemets mål och verkligheten i deras distribuerade miljöer.
Konsistens i CAP är inte detsamma som konsekvensen i ACID-transaktioner . I CAP-teorem hänvisar det till lineariserbarhet eller stark konsistens . Det innebär att alla noder i ett distribuerat system alltid måste presentera en enda, uppdaterad vy av data , oavsett vilken nod som behandlar begäran. Det betyder att varje läsoperation återspeglar den senaste skrivningen, oavsett vilken nod du frågar efter.
💡 Konsistens i ACID, å andra sidan, fokuserar på att säkerställa att en transaktion för databasen från ett giltigt tillstånd till ett annat giltigt tillstånd, enligt reglerna som definieras av databasschemat. Det handlar mer om att upprätthålla integritetsbegränsningar (som främmande nycklar, unika begränsningar, etc) och att se till att databasen inte lämnas i ett ogiltigt tillstånd, även inför krascher.
Tillgänglighet i CAP innebär att varje nod som inte misslyckas måste returnera ett svar för varje begäran den tar emot, oavsett nätverkspartitioner . Med andra ord, om en frisk nod får en begäran måste den bearbeta och svara på den. Men CAP garanterar inte att svaret alltid kommer att vara "korrekt" eller uppdaterat - det säkerställer bara att noden inte misslyckas tyst (till exempel i AP-system kan noder svara med inaktuella data under en partition för att säkerställa tillgänglighet ).
💡 Eric Brewer (den ursprungliga författaren till CAP) beskrev ursprungligen den här egenskapen lite mer flexibelt som: "nästan alla frågor borde få ett svar". Men i det formella beviset för CAP gjordes tillgängligheten strängare, vilket krävde att "varje fråga ska få ett svar så länge som noden som hanterar den är sund".
I praktiken är dock tillgänglighet inte en absolut garanti – det beror ofta på systemspecifika begränsningar, som hur länge du är villig att vänta på ett svar. För verkliga system spelar svarstid (eller timeouts) en avgörande roll i utformningen av din SLA (servicenivåavtal), även om CAP själv inte direkt tar hänsyn till latens. Mer om det i detta blogginlägg .
Partitionstolerans handlar om att överleva nätverksfel. Om noder inte kan kommunicera på grund av en nätverksdelning (partition), måste systemet fortfarande uppfylla sina garantier för konsistens eller tillgänglighet, beroende på dess designval. En partition inträffar när noder inte kan kommunicera på grund av tappade paket, timeouts eller nätverksuppdelningar.
Distribuerade system lever inte i en sagovärld med perfekta nätverk. Paketen tappas, timeouts inträffar och fördröjningstoppar är oundvikliga. På grund av detta är partitionstolerans inte förhandlingsbar i alla distribuerade system - partitioner kommer att hända förr eller senare, så du kan inte "välja" att ignorera det, oavsett hur frestande det kan låta.
I CAP betyder partitionstolerans inte att systemet fortsätter att köras som om ingenting hänt. Det betyder att systemet måste bestämma om det ska prioritera tillgänglighet (AP) eller konsekvens (CP) under en partition. Om du skulle ignorera partitionstolerans, skulle du i princip bygga ett icke-distribuerat monolitiskt system.
Det enklaste sättet att förstå CAP är att överväga en nätverkspartition - en situation där två delar av ett distribuerat system inte kan kommunicera med varandra. I ett sådant scenario står systemet inför tre möjliga utfall:
Under en partition kan systemet alltså bara uppfylla två av de tre egenskaperna (C, A eller P) . När partitionen är löst (dvs. noderna interagerar igen) kan systemet återfå alla tre egenskaperna, men under själva partitionen är avvägningar oundvikliga.
En konsekvens av satsen för asynkrona system är att endast tre kombinationer av konsistens, tillgänglighet och partitionstolerans är möjliga:
System av den här typen svarar på frågor, men den data som returneras kanske inte alltid är uppdaterad, med långsammare uppdateringar av data men "alltid" tillgänglig. Exempel på ett sådant system är DNS, DynamoDB och Cassandra.
System av denna typ returnerar alltid uppdaterade data, men vissa, eller till och med alla, noder i systemet kanske inte svarar om de partitioneras. Det ger atomära uppdateringar men kan leda till timeout. NoSQL-databaser som Google BigTable, MongoDB, HBase och Redis är alla system av denna typ.
System av denna typ returnerar alltid uppdaterad data när det inte finns några partitioner. På grund av den sista begränsningen används sådana system vanligtvis endast inom en maskin. Exempel är klassiska relationsdatabaser.
I verkligheten väljer vi mellan CP och AP eftersom CA i grunden är en monolit utan partitioner. För storskaliga system kan konstruktörer inte överge P och har därför ett svårt val mellan C och A.
I CA betyder nodfel fullständig otillgänglighet för tjänsten. Men detta inaktiverar inte skalbarhet, eftersom vi kan klona oberoende monoliter och fördela belastningen över dem
CAP-teoremet har varit ett grundläggande koncept i distribuerade system, men det är inte utan sina begränsningar. För all sin klarhet i att presentera idén om avvägningar, har CAP-satsen ofta kritiserats för att förenkla komplexa verkligheter, vilket har lett till missförstånd och felaktiga tillämpningar.
En av de vanligaste kritikerna är att CAP-teoremets avvägningar – att välja mellan konsistens (C) och tillgänglighet (A) – bara gäller när en nätverkspartition (P) faktiskt inträffar. I normal drift, när nätverket är stabilt och inga partitioner existerar, finns det ingen inneboende kompromiss mellan konsekvens och tillgänglighet.
Dessutom är dessa avvägningar inte universella över hela systemet. Inom samma distribuerade system:
Denna nyans går ofta förlorad i diskussioner på hög nivå om CAP, vilket leder till alltför förenklade klassificeringar av system som "CP" eller "AP" över hela linjen.
En annan viktig kritik är att CAP-satsen inte tar hänsyn till latens , även om latens och partitionering är djupt sammankopplade i praktiken. Till exempel:
I verkliga distribuerade system, när en partition eller hög latens inträffar, måste systemet fatta ett beslut inom en timeoutperiod : prioritera tillgänglighet genom att returnera ett eventuellt inaktuellt resultat, eller prioritera konsekvens genom att vänta längre (och eventuellt misslyckas med att svara). CAP:s binära syn fångar inte komplexiteten i dessa beslut.
CAP-satsen presenterar konsistens, tillgänglighet och partitionstolerans som binära egenskaper – antingen har du dem eller så har du inte. Men i praktiken existerar alla tre egenskaperna på ett spektrum :
Denna kontinuerliga karaktär av egenskaper gör CAP alltför förenklat för att modellera komplexiteten hos moderna distribuerade system.
Även om CAP revolutionerade vår förståelse av avvägningar i distribuerade system, är det inte det sista ordet i ämnet. PACELC-satsen som beskrivs av Daniel J. Abadi anses vara en alternativ metod för design av distribuerade system. Den är baserad på CAP-modellen, men förutom konsekvens, tillgänglighet och partitionstolerans inkluderar den även latens och logisk uteslutning mellan kombinationer av dessa koncept.
PACELC introducerar två distinkta driftsätt för distribuerade system:
Även om partitioner är oundvikliga i distribuerade system är de sällsynta jämfört med de utmaningar som uppstår under normal drift. I moderna distribuerade system är latens ofta en större flaskhals än nätverkspartitioner, särskilt för globala applikationer. Det är här PACELC fokuserar - genom att ta itu med de avvägningar som uppstår när systemet fungerar utan partitioner. Till skillnad från CAP, som enbart fokuserar på beteende under felscenarier, betonar PACELC de beslut som arkitekter måste fatta varje dag för att balansera latens (L) och konsekvens (C) :
Genom att utöka konversationen bortom partitioner till att omfatta normal drift, säkerställer PACELC att den dagliga prestandan för distribuerade system behandlas med den vikt den förtjänar.
Formuleringen av CAP-teoremet har varit en betydande händelse i samhället, och studier av dess inverkan på distribuerade systemdesign har visat att designers av distribuerade system inte bör begränsa systemet till två egenskaper - de bör sträva efter att maximera de garantier som krävs i varje särskilt fall. För detta ändamål är det rimligt att dela upp systemet i segment, som vart och ett har sina egna krav, och att utforma systemet utifrån kraven i vart och ett av segmenten.
CAP-satsen har varit en hörnsten i distribuerade systemtänkande i årtionden. Det gav oss ett ramverk för att resonera om de inneboende avvägningarna av konsekvens, tillgänglighet och partitionstolerans. Men på många sätt är det en förenkling av verkligheten, antar binära val och ignorerar kritiska faktorer som latens.
PACELC bygger på CAP och erkänner att:
Både CAP och PACELC är värdefulla verktyg, men inte heller ett steg-för-steg-recept för att bygga system. Istället tillhandahåller de mentala modeller för att utvärdera avvägningar och förstå gränserna för distribuerade arkitekturer.
Tack för att du läser!
Nyfiken på något eller har tankar att dela med dig av? Lämna din kommentar nedan! Kolla in min blogg eller följ mig via LinkedIn , Substack eller Telegram .