sql >> Databasteknik >  >> RDS >> Mysql

Bästa metoder för skalning av databaser:Del 1

Alla ni har hört talas om skalning - din arkitektur bör vara skalbar, du bör kunna skala upp för att möta efterfrågan, så vidare och så vidare. Vad betyder det när vi pratar om databaser? Hur ser skalningen ut bakom kulisserna? Detta ämne är omfattande och det finns inget sätt att täcka alla aspekter. Denna serie med två blogginlägg är ett försök att ge dig en inblick i ämnet databasskalbarhet.

Varför skalar vi?

Låt oss först ta en titt på vad skalbarhet handlar om. Kortfattat talar vi om förmågan att hantera högre belastning av dina databassystem. Det kan handla om att hantera kortvariga toppar i aktiviteten, det kan handla om att hantera en successivt ökad arbetsbelastning i din databasmiljö. Det kan finnas många skäl att överväga skalning. De flesta av dem kommer med sina egna utmaningar. Vi kan lägga lite tid på att gå igenom exempel på situationen där vi kanske vill skala ut.

Öka resursförbrukningen

Detta är den mest generiska - din belastning har ökat till den punkt där dina befintliga resurser inte längre kan hantera det. Det kan vara vad som helst. CPU-belastningen har ökat och ditt databaskluster kan inte längre leverera data med rimlig och stabil frågekörningstid. Minnesutnyttjandet har vuxit till en sådan grad att databasen inte längre är CPU-bunden utan blev I/O-bunden och som sådan har databasnodernas prestanda minskat avsevärt. Nätverk kan också vara en bootle-neck. Du kan bli förvånad över att se vilka gränser relaterade till nätverksarbete har dina molninstanser tilldelade. I själva verket kan detta bli den vanligaste gränsen du måste hantera eftersom nätverket är allt i molnet - inte bara data som skickas mellan applikationen och databasen utan även lagring är kopplad över nätverket. Det kan också vara diskanvändning - du har bara slut på diskutrymme eller, mer troligt, eftersom vi kan ha ganska stora diskar nuförtiden, växte databasstorleken större än den "hanterbara" storleken. Underhåll som schemaändring blir en utmaning, prestandan minskar på grund av datastorleken, säkerhetskopieringar tar evigheter att slutföra. Alla dessa fall kan vara ett giltigt fall för ett behov av uppskalning.

Plötslig ökning av arbetsbelastningen

Ett annat exempel där skalning krävs är en plötslig ökning av arbetsbelastningen. Av någon anledning (vare sig det är marknadsföringsinsatser, innehåll som blir viralt, nödsituationer eller liknande) upplever din infrastruktur en betydande ökning av belastningen på databasklustret. CPU-belastning går över taket, disk I/O saktar ner frågorna etc. I stort sett varje resurs som vi nämnde i föregående avsnitt kan överbelastas och börja orsaka problem.

Planerad operation

Den tredje anledningen som vi skulle vilja lyfta fram är den mer generiska - någon sorts planerad operation. Det kan vara en planerad marknadsföringsaktivitet som du förväntar dig att få in mer trafik, Black Friday, belastningstester eller i stort sett vad som helst som du vet i förväg.

Var och en av dessa orsaker har sina egna egenskaper. Om du kan planera i förväg kan du förbereda processen i detalj, testa den och utföra den när du känner för det. Du kommer med största sannolikhet att gilla att göra det under en period med "låg trafik", så länge något sådant finns i dina arbetsbelastningar (det behöver inte finnas). Å andra sidan kommer plötsliga toppar i belastningen, särskilt om de är betydande nog att påverka produktionen, tvinga fram en omedelbar reaktion, oavsett hur förberedd du är och hur säker den är - om dina tjänster redan är påverkade kan du lika gärna bara gå på det istället för att vänta.

Typer av databasskalning

Det finns två huvudtyper av skalning:vertikal och horisontell. Båda har för- och nackdelar, båda är användbara i olika situationer. Låt oss ta en titt på dem och diskutera användningsfall för båda scenarierna.

Vertikal skalning

Denna skalningsmetod är förmodligen den äldsta:om din hårdvara inte är kraftig nog för att hantera arbetsbelastningen, förbättra den. Vi pratar här helt enkelt om att lägga till resurser till befintliga noder med en avsikt att göra dem tillräckligt kapabla att hantera de uppgifter som ges. Detta har några återverkningar som vi skulle vilja gå igenom.

Fördelar med vertikal skalning

Det viktigaste är att allt förblir detsamma. Du hade tre noder i ett databaskluster, du har fortfarande tre noder, bara mer kapabel. Det finns inget behov av att designa om din miljö, ändra hur applikationen ska komma åt databasen - allt förblir exakt detsamma eftersom konfigurationsmässigt ingenting egentligen har förändrats.

En annan betydande fördel med vertikal skalning är att den kan vara mycket snabb, särskilt i molnmiljöer. Hela processen går i stort sett ut på att stoppa den befintliga noden, göra förändringen i hårdvaran, starta noden igen. För klassiska, lokala inställningar, utan någon virtualisering, kan detta vara knepigt - du kanske inte har snabbare CPU:er tillgängliga att byta, att uppgradera diskar till större eller snabbare kan också vara tidskrävande, men för molnmiljöer, vare sig det är offentliga eller privata, detta kan vara så enkelt som att köra tre kommandon:stoppa instans, uppgradera instans till större storlek, starta instans. Virtuella IP:er och återanslutningsbara volymer gör det enkelt att flytta runt data mellan instanser.

Nackdelar med vertikal skalning

Den största nackdelen med vertikal skalning är att det helt enkelt har sina gränser. Om du kör på den största tillgängliga instansstorleken, med de snabbaste diskvolymerna, finns det inte mycket annat du kan göra. Det är inte heller så lätt att öka prestandan för ditt databaskluster avsevärt. Det beror mest på den initiala instansstorleken, men om du redan kör ganska presterande noder kanske du inte kan uppnå 10x skalning med vertikal skalning. Noder som skulle vara 10 gånger snabbare kanske helt enkelt inte existerar.

Horisontell skalning

Horisontell skalning är en annan best. Istället för att gå upp med instansstorleken stannar vi på samma nivå men vi expanderar horisontellt genom att lägga till fler noder. Återigen, det finns för- och nackdelar med denna metod.

Fördelar med horisontell skalning

Den största fördelen med horisontell skalning är att teoretiskt sett är himlen gränsen. Det finns ingen konstgjord hård gräns för utskalning, även om det finns gränser, främst på grund av att kommunikation inom kluster blir större och större overhead för varje ny nod som läggs till i klustret.

En annan betydande fördel skulle vara att du kan skala upp klustret utan behov av stillestånd. Om du vill uppgradera hårdvaran måste du stoppa instansen, uppgradera den och sedan börja om. Om du vill lägga till fler noder till klustret, är allt du behöver göra att tillhandahålla dessa noder, installera vilken programvara du behöver, inklusive databasen, och låta den gå med i klustret. Alternativt (beroende på om klustret har interna metoder för att tillhandahålla nya noder med data) kan du behöva tillhandahålla det med data på egen hand. Vanligtvis är det dock en automatiserad process.

Nackdelar med horisontell skalning

Det största problemet som du måste ta itu med är att att lägga till fler och fler noder gör det svårt att hantera hela miljön. Du måste kunna se vilka noder som är tillgängliga, en sådan lista måste underhållas och uppdateras med varje ny nod som skapas. Du kan behöva externa lösningar som katalogtjänst (Konsul eller Etcd) för att hålla koll på noderna och deras tillstånd. Detta ökar uppenbarligen komplexiteten i hela miljön.

Ett annat potentiellt problem är att utskalningsprocessen tar tid. Att lägga till nya noder och förse dem med programvara och framför allt data kräver tid. Hur mycket, det beror på hårdvaran (främst I/O och nätverksgenomströmning) och storleken på data. För stora inställningar kan detta vara en betydande tid och detta kan vara en blockerare för situationer där uppskalningen måste ske omedelbart. Väntetimmar för att lägga till nya noder kanske inte är acceptabelt om databasklustret påverkas i den utsträckningen att operationer inte utförs korrekt.

Skalningsförutsättningar

Datareplikering

Innan något försök till skalning kan göras måste din miljö uppfylla ett par krav. Till att börja med måste din applikation kunna dra fördel av mer än en nod. Om den bara kan använda en nod är dina alternativ ganska begränsade till vertikal skalning. Du kan öka storleken på en sådan nod eller lägga till några hårdvaruresurser till barmetallservern och göra den mer presterande men det är det bästa du kan göra:du kommer alltid att begränsas av tillgången på mer presterande hårdvara och så småningom kommer du att hitta själv utan möjlighet att skala upp ytterligare.

Å andra sidan, om du har möjlighet att använda flera databasnoder av din applikation, kan du dra nytta av horisontell skalning. Låt oss stanna här och diskutera vad du behöver för att faktiskt kunna använda flera noder till sin fulla potential.

Till att börja med, möjligheten att dela upp läsningar från skrivningar. Traditionellt ansluter applikationen till bara en nod. Den noden används för att hantera alla skrivningar och alla läsningar som exekveras av applikationen.

Att lägga till en andra nod till klustret, från skalningssynpunkt, ändrar ingenting . Du måste komma ihåg att om en nod skulle misslyckas kommer den andra att behöva hantera trafiken, så summan av belastningen över båda noderna bör inte vid något tillfälle vara för hög för en enda nod att hantera.

Med tre tillgängliga noder kan du fullt ut använda två noder. Detta gör att vi kan skala ut en del av lästrafiken:om en nod har 100 % kapacitet (och vi hellre kör högst 70 %), så representerar två noder 200 %. Tre noder:300 %. Om en nod är nere och om vi pressar återstående noder nästan till gränsen, kan vi säga att vi kan arbeta med 170 - 180 % av en enda nodkapacitet om klustret är försämrat. Det ger oss 60 % belastning på varje nod om alla tre noderna är tillgängliga.

Tänk på att vi bara pratar om skalning av läsningar för närvarande . Replikering kan inte vid någon tidpunkt förbättra din skrivkapacitet. I asynkron replikering har du bara en skrivare (master), och för den synkrona replikeringen, som Galera, där datasetet delas över alla noder, måste varje skrivning som sker på en nod utföras på de återstående noderna i klunga.

I ett Galera-kluster med tre noder, om du skriver en rad, skriver du faktiskt tre rader, en för varje nod. Att lägga till fler noder eller repliker kommer inte att göra någon skillnad. Istället för att skriva samma rad på tre noder skriver du den på fem. Det är därför du delar upp dina skrivningar i ett multi-master-kluster, där datamängden delas över alla noder (det finns multi-master-kluster där data delas, till exempel MySQL NDB-kluster - här är skrivskalbarhetsberättelsen helt annorlunda), är inte så vettigt. Det lägger till overhead för att hantera potentiella skrivkonflikter över alla noder samtidigt som det egentligen inte förändrar någonting angående den totala skrivkapaciteten.

Lastbalansering och läs-/skrivdelning

Möjligheten att dela läsningar från skrivningar är ett måste om du vill skala dina läsningar i asynkrona replikeringsinställningar. Du måste kunna skicka skrivtrafik till en nod och sedan skicka läsningarna till alla noder i replikeringstopologin. Som vi nämnde tidigare är den här funktionen också ganska användbar i multi-master-klustren eftersom den tillåter oss att ta bort skrivkonflikter som kan uppstå om du försöker distribuera skrivningarna över flera noder i klustret. Hur kan vi utföra läs/skrivdelningen? Det finns flera metoder du kan använda för att göra det. Låt oss gräva lite i det här ämnet.

Applikationsnivå R/W split

Det enklaste scenariot, det minst frekventa också:din applikation kan konfigureras vilka noder som ska ta emot skrivningar och vilka noder som ska ta emot läsningar. Denna funktionalitet kan konfigureras på ett par sätt, det enklaste är den hårdkodade listan över noder, men det kan också vara något i stil med dynamisk nodinventering uppdaterad av bakgrundstrådar. Det största problemet med detta tillvägagångssätt är att hela logiken måste skrivas som en del av applikationen. Med en hårdkodad lista med noder skulle det enklaste scenariot kräva ändringar av applikationskoden för varje ändring i replikeringstopologin. Å andra sidan skulle mer avancerade lösningar som att implementera en tjänsteupptäckt vara mer komplexa att underhålla på lång sikt.

R/W delad kontakt

Ett annat alternativ skulle vara att använda en anslutning för att utföra en läs/skrivdelning. Inte alla av dem har det här alternativet, men vissa har det. Ett exempel skulle vara php-mysqlnd eller Connector/J. Hur den är integrerad i applikationen kan skilja sig beroende på själva kontakten. I vissa fall måste konfigurationen göras i applikationen, i vissa fall måste den göras i en separat konfigurationsfil för anslutningen. Fördelen med detta tillvägagångssätt är att även om du måste utöka din applikation så är det mesta av den nya koden redo att användas och underhålls av externa källor. Det gör det lättare att hantera sådana inställningar och du måste skriva mindre kod (om någon).

R/W uppdelad i lastbalanserare

Äntligen en av de bästa lösningarna:lastbalanserare. Tanken är enkel - skicka dina data genom en lastbalanserare som kommer att kunna skilja mellan läsning och skrivning och skicka dem till en lämplig plats. Detta är en stor förbättring ur användbarhetssynpunkt eftersom vi kan separera databasupptäckt och frågedirigering från applikationen. Det enda programmet behöver göra är att skicka databastrafiken till en enda slutpunkt som består av ett värdnamn och en port. Resten sker i bakgrunden. Lastbalanserare arbetar med att dirigera frågorna till en backend-databasnoder. Lastbalanserare kan också göra replikeringstopologiupptäckt eller så kan du implementera en korrekt tjänsteinventering med hjälp av etcd eller konsul och uppdatera den genom dina infrastrukturorkestreringsverktyg som Ansible.

Detta avslutar den första delen av denna blogg. I den andra kommer vi att diskutera de utmaningar vi står inför när vi skalar databasnivån. Vi kommer också att diskutera några sätt på vilka vi kan skala ut våra databaskluster.


  1. Värdpaket på Chocolatey

  2. Ytterligare en anledning att använda NOEXPAND-tips i Enterprise Edition

  3. Skillnad mellan BYTE och CHAR i kolumndatatyper

  4. Hur byter man databaser i psql?