sql >> Database teknologi >  >> RDS >> Mysql

En guide til at forstå databaseskaleringsmønstre

Der er mange artikler online, der beskriver databasens skalerbarhedsmønstre, men de er for det meste spredte artikler - bare teknikker, der er defineret tilfældigt uden megen kontekst. Jeg oplever, at de ikke er defineret trin for trin, og diskuterer ikke, hvornår man skal vælge hvilken skaleringsmulighed, hvilke skaleringsmuligheder der er gennemførlige i praksis, og hvorfor.

Derfor planlægger jeg at diskutere nogle af teknikkerne i detaljer i fremtidige artikler. Til at starte med føler jeg, at det er bedre, hvis jeg diskuterer trinvise teknikker med en eller anden sammenhæng på min egen måde. Denne artikel er en artikel på højt niveau - jeg vil ikke diskutere skaleringsteknikker i detaljer her, men vil give et overblik. Så lad os komme i gang.

Et casestudie

Antag, at du har bygget en startup, som tilbyder kørselsdeling til en billig pris. I første omgang, når du starter, målretter du mod en by og har næppe snesevis af kunder efter din første annonce.

Du gemmer alle kunder, rejser, lokationer, reservationsdata og kunderejsehistorik i den samme database eller højst sandsynligt i en enkelt fysisk maskine. Der er ingen fancy caching eller big data pipeline til at løse problemer, da din app er meget ny. Dette er perfekt til din brug i øjeblikket, da der er meget få kunder, og dit system for eksempel næppe booker 1 tur på 5 minutter.

Men som tiden går, begynder flere at tilmelde sig dit system, da du er den billigste service på markedet og takket være din kampagne og annoncer. Du begynder at booke for eksempel 10 bookinger i minuttet, og langsomt stiger antallet til 20, 30 bookinger i minuttet.

På dette tidspunkt indser du, at systemet er begyndt at præstere dårligt:​​API-latenstiden er steget meget, og nogle transaktioner låser sig eller sulter, og til sidst mislykkes de. Din app tager længere tid at svare, hvilket forårsager kundernes utilfredshed. Hvad kan du gøre for at løse problemet?

Mønster 1 - Forespørgselsoptimering og implementering af forbindelsespulje:

Den første løsning, der kommer i tankerne, er, at cachen ofte bruger ikke-dynamiske data som bookinghistorik, betalingshistorik, brugerprofiler og så videre. Men efter denne applikationslagscaching kan du ikke løse latensproblemet med API'er, der afslører dynamiske data som den aktuelle chaufførs placering eller de nærmeste førerhuse for en given kunde eller aktuelle turomkostninger på et bestemt tidspunkt efter turens start.

Du identificerer, at din database sandsynligvis er stærkt normaliseret, så du introducerer nogle redundante kolonner (disse kolonner vises ofte i WHERE eller JOIN ON klausul i forespørgsler) i meget brugte tabeller af hensyn til denormalisering. Dette reducerer joinforespørgsler, deler en stor forespørgsel op i flere mindre forespørgsler og tilføjer deres resultater i applikationslaget.

En anden parallel optimering, som du kan gøre, er at tilpasse databaseforbindelser. Databaseklientbiblioteker og eksterne biblioteker er tilgængelige på næsten alle programmeringssprog. Du kan bruge forbindelsespuljebiblioteker til at cache databaseforbindelser eller kan konfigurere forbindelsespuljestørrelsen i selve databasestyringssystemet.

Det er dyrt at oprette en netværksforbindelse, da det kræver noget frem og tilbage kommunikation mellem klient og server. Pooling af forbindelser kan hjælpe dig med at optimere antallet af forbindelser. Forbindelsespuljebiblioteker kan hjælpe dig med at multiplekse forbindelser - flere applikationstråde kan bruge den samme databaseforbindelse. Jeg skal se, om jeg kan forklare forbindelsespooling i detaljer i en separat artikel senere.

Du måler latens for dine API'er og find sandsynligvis 20-50 % eller mere reduceret latenstid. Dette er god optimering på dette tidspunkt.

Du har nu skaleret din virksomhed til en by mere, flere kunder tilmelder sig, du begynder langsomt at lave 80-100 bookinger i minuttet. Dit system er ikke i stand til at håndtere denne skala. Igen ser du API-latenstiden er steget, databaselaget har givet op, men denne gang er der ingen forespørgselsoptimering, der giver dig nogen væsentlig ydelsesforøgelse. Du tjekker systemmetrikken, du finder, at diskpladsen er næsten fuld, CPU'en er optaget 80 % af tiden, RAM fyldes meget hurtigt op.

Mønster 2 - Lodret skalering eller opskalering:

Efter at have undersøgt alle systemmålinger ved du, at der ikke er nogen anden nem løsning i stedet for at opgradere systemets hardware. Du opgraderer din RAM-størrelse med 2 gange, opgraderer diskplads med for eksempel 3 gange eller mere. Dette kaldes lodret skalering eller opskalering af dit system. Du informerer dit infrastrukturteam eller sender team- eller tredjepartsdatacenteragenter til at opgradere din maskine.

Men hvordan konfigurerer du maskinen til vertikal skalering?

Du tildeler en større maskine. En tilgang er ikke at migrere data manuelt fra gammel maskine, men sæt den nye maskine som replica til den eksisterende maskine (primary )-lav en midlertidig primary replica konfiguration. Lad replikationen ske naturligt. Når replikeringen er færdig, skal du fremme den nye maskine til primær og tage den ældre maskine offline. Da den større maskine forventes at betjene alle anmodninger, vil al læsning/skrivning ske på denne maskine.

Fedt nok. Dit system er oppe og køre igen med øget ydeevne.

Din virksomhed klarer sig meget godt, og du beslutter dig for at skalere til 3 flere byer — du er nu operationel i 5 byer i alt. Trafikken er 3 gange end tidligere, du forventes at foretage omkring 300 bookinger i minuttet. Inden du overhovedet når dette målbooking, rammer du igen præstationsknasten, databaseindeksstørrelsen stiger kraftigt i hukommelsen, den har brug for konstant vedligeholdelse, tabelscanning med indeks bliver langsommere end nogensinde. Du beregner omkostningerne ved at opskalere maskinen yderligere, men er ikke overbevist om omkostningerne. Hvad gør du nu?

Mønster 3 - Command Query Responsibility Segregation (CQRS):

Du identificerer, at den store maskine ikke er i stand til at håndtere alt read/write anmodninger. Også i de fleste tilfælde har enhver virksomhed brug for transaktionsevne på write men ikke på read operationer. Du har det også fint med en lille smule inkonsekvent eller forsinket read drift og din virksomhed har heller ikke noget problem med det. Du ser en mulighed, hvor det kan være en god mulighed at adskille read &write operationer fysisk maskinmæssigt. Det vil skabe mulighed for individuelle maskiner til at håndtere mere read/write operationer.

Du tager nu to store maskiner mere og sætter dem op som replica til den aktuelle maskine. Databasereplikering vil sørge for at distribuere data fra primary maskine til replica maskiner. Du navigerer i alle læste forespørgsler (Forespørgsel (Q ) i CQRS ) til replikaerne — enhver replica kan betjene enhver læseanmodning, navigerer du alle skriveforespørgsler (Kommando (C ) i CQRS ) til den primary . Der kan være lidt forsinkelse i replikeringen, men i henhold til din virksomheds brug er det fint.

De fleste af de mellemstore opstartsvirksomheder, som hver dag betjener få hundrede tusinde forespørgsler, kan overleve med opsætning af primær replika, forudsat at de med jævne mellemrum arkiverer ældre data.

Nu du skalerer til 2 flere byer, kan du se, at din primary er ikke i stand til at håndtere alt write anmodninger. Mange write anmodninger har latency. Desuden er forsinkelsen mellem primary &replica nogle gange påvirker kunder og chauffører f.eks. - når turen slutter, betaler kunden chaufføren med succes, men chaufføren er ikke i stand til at se betalingen, da kundens aktivitet er en write anmodning, der går til den primary , mens chaufførens aktivitet er en read anmodning, der går til en af ​​replikaerne. Dit samlede system er så langsomt, at chaufføren ikke er i stand til at se betalingen i mindst et halvt minut - frustrerende for både chauffør og kunde. Hvordan løser du det?

Mønster 4 - Multiprimær replikering

Du har skaleret rigtig godt med primary-replica konfiguration, men nu har du brug for mere skriveydelse. Du er måske klar til at gå en lille smule på kompromis med read anmode om ydeevne. Hvorfor ikke distribuere skriveanmodningen til en replica også?

I en multi-primary konfiguration, kan alle maskinerne fungere som både primary &replica . Du kan tænke på multi-primary som en cirkel af maskiner siger A->B->C->D->A . B kan replikere data fra A , C kan replikere data fra B , D kan replikere data fra C , A kan replikere data fra D . Du kan skrive data til enhver node, mens du læser data, kan du udsende forespørgslen til alle noder, hvem der svarer, returnerer det. Alle noder vil have samme databaseskema, samme sæt tabeller, indeks osv. Så du skal sikre dig, at der ikke er nogen kollision i id på tværs af noder i den samme tabel, ellers ville flere noder under udsendelse returnere forskellige data for det samme id .

Generelt er det bedre at bruge UUID eller GUID for id. Endnu en ulempe ved denne teknik er - read forespørgsler kan være ineffektive, da det involverer udsendelse af forespørgsler og opnåelse af det korrekte resultat - dybest set scatter collection-tilgang.

Nu skalerer du til 5 flere byer, og dit system har ondt igen. Du forventes at håndtere omkring 50 anmodninger i sekundet. Du har et desperat behov for at håndtere et stort antal samtidige anmodninger. Hvordan opnår du det?

Mønster 5 - Partitionering:

Du ved, at din location database er noget, der bliver høj write &read Trafik. Sandsynligvis write:read forholdet er 7:3 . Dette lægger et stort pres på de eksisterende databaser. location tabeller indeholder få primære data som longitude , latitude , timestamp , driver id , trip id osv. Det har ikke meget at gøre med brugerrejser, brugerdata, betalingsdata osv. Hvad med at adskille location tabeller i et separat databaseskema? Hvad med at placere den database i separate maskiner med korrekt primary replica eller multi-primary konfiguration?

Dette kaldes opdeling af data efter funktionalitet. Forskellige databaser kan være vært for data kategoriseret efter forskellig funktionalitet, hvis det kræves, kan resultatet aggregeres i backend-laget. Ved at bruge denne teknik kan du fokusere på at skalere de funktioner godt, som kræver høj read/write anmodninger. Selvom backend- eller applikationslaget er nødt til at påtage sig ansvaret for at samle resultaterne, når det er nødvendigt, hvilket sandsynligvis vil resultere i flere kodeændringer.

Forestil dig nu, at du har udvidet din virksomhed til i alt 20 byer i dit land og planlægger at udvide til Australien snart. Din stigende efterspørgsel efter app kræver hurtigere og hurtigere respons. Ingen af ​​ovenstående metoder kan hjælpe dig til det yderste nu. Du skal skalere dit system på en sådan måde, at udvidelse til andre lande/regioner ikke altid kræver, at du foretager hyppige ingeniør- eller arkitekturændringer. Hvordan gør du det?

Mønster 6 - Vandret skalering:

Du googler meget, læser meget om, hvordan andre virksomheder har løst problemet - og kommer til den konklusion, at du skal skalere vandret. Du tildeler f.eks. 50 maskiner - alle har det samme databaseskema, som igen indeholder det samme sæt tabeller. Alle maskinerne rummer bare en del af data.

Da alle databaser indeholder samme sæt tabeller, kan du designe systemet på en sådan måde, at lokaliteten af ​​data er der, dvs. alle relaterede data lander i samme maskine. Hver maskine kan have deres egne replikaer, replikaer kan bruges til fejlgendannelse. Hver af databaserne kaldes shard . En fysisk maskine kan have en eller flere shards - det er op til dit design, hvordan du vil. Du skal beslutte dig for sharding key på en sådan måde, at en enkelt sharding key refererer altid til den samme maskine. Så du kan forestille dig en masse maskiner, der alle indeholder relaterede data i samme sæt tabeller, read/write anmodninger om den samme række eller det samme sæt ressourceland i den samme databasemaskine.

Sharding er generelt svært - det siger i hvert fald ingeniører fra forskellige virksomheder. Men når du betjener millioner eller milliarder af anmodninger, er du nødt til at træffe en så svær beslutning.

Jeg vil diskutere sharding mere detaljeret i mit næste indlæg, så hold min fristelse tilbage til at diskutere mere i dette indlæg.

Nu da du har sharding på plads, er du sikker på, at du kan skalere til mange lande. Din virksomhed er vokset så meget, at investorer presser dig til at skalere forretningen på tværs af kontinenter. Du ser igen et problem her. API-forsinkelse igen. Din tjeneste er hostet i USA, og folk fra Vietnam har svært ved at bestille ture. Hvorfor? Hvad gør du ved det?

Mønster 7 - Datacenter Wise Partition:

Din virksomhed vokser i Amerika, Sydasien og i få lande i Europa. Du foretager millioner af bookinger dagligt med milliarder af anmodninger, der rammer din server. Tillykke - dette er et højdepunkt for din virksomhed.

Men da anmodninger fra appen skal rejse på tværs af kontinenter gennem hundredvis eller tusindvis af servere på internettet, opstår forsinkelsen. Hvad med at distribuere trafik på tværs af datacentre? Du kan oprette et datacenter i Singapore, der håndterer alle anmodninger fra Sydasien, datacenter i Tyskland kan håndtere alle anmodninger fra europæiske lande, og et datacenter i Californien kan håndtere alle anmodninger fra USA.

Du aktiverer også krydsdatacenterreplikering, som hjælper med at genoprette katastrofen. Så hvis Californiens datacenter replikerer til Singapores datacenter, i tilfælde af at Californiens datacenter går ned på grund af elektricitetsproblem eller naturkatastrofer, kan alle USA-anmodninger falde tilbage til Singapores datacenter og så videre.

Denne skaleringsteknik er nyttig, når du har millioner af kunder at betjene på tværs af lande, og du ikke kan imødekomme noget tab af data, du skal altid opretholde systemets tilgængelighed.

Disse er nogle generelle trinvise teknikker til databaseskalering. Selvom de fleste af ingeniørerne ikke får nok chancer for at implementere disse teknikker, men som helhed er det bedre at få en bredere idé om et sådant system, som i fremtiden kan hjælpe dig med at lave bedre system- og arkitekturdesign.

I mine næste artikler vil jeg forsøge at diskutere nogle af begreberne i detaljer. Du er velkommen til at give passende feedback til dette indlæg, hvis nogen.

Artiklen er oprindeligt publiceret på forfatterens mediekonto:https://medium.com/@kousiknath/understanding-database-scaling-patterns-ac24e5223522



  1. opdel søgeord til post php mysql

  2. Vælg en MySQL-database på Linux via kommandolinjen

  3. Sådan opretter du tabel med identitetskolonne

  4. Fix Error Msg 4151 "Typen af ​​det første argument til NULLIF kan ikke være NULL konstanten, fordi typen af ​​det første argument skal være kendt" i SQL Server