sql >> Database >  >> RDS >> Mysql

Een gids voor het begrijpen van schaalpatronen voor databases

Er zijn veel artikelen online die schaalbaarheidspatronen van databases beschrijven, maar het zijn meestal verspreide artikelen - alleen technieken die lukraak worden gedefinieerd zonder veel context. Ik vind dat ze niet stapsgewijs worden gedefinieerd en bespreek niet wanneer welke schaaloptie moet worden gekozen, welke schaalopties in de praktijk haalbaar zijn en waarom.

Daarom ben ik van plan om enkele van de technieken in toekomstige artikelen in detail te bespreken. Om te beginnen denk ik dat het beter is als ik stap voor stap technieken bespreek met wat context op mijn eigen manier. Dit artikel is een artikel op hoog niveau - ik zal hier niet in detail schaaltechnieken bespreken, maar zal een overzicht geven. Dus laten we beginnen.

Een casestudy

Stel dat je een startup hebt gebouwd die het delen van ritten tegen lage kosten aanbiedt. Als je begint, richt je je in eerste instantie op een stad en heb je na je eerste advertentie nauwelijks tientallen klanten.

U slaat alle klanten, reizen, locaties, boekingsgegevens en klantreisgeschiedenis op in dezelfde database of hoogstwaarschijnlijk in één fysieke machine. Er is geen fancy caching of big data-pipeline om problemen op te lossen, aangezien uw app erg nieuw is. Dit is perfect voor uw gebruik op dit moment aangezien er zeer weinig klanten zijn en uw systeem bijvoorbeeld nauwelijks 1 reis in 5 minuten boekt.

Maar naarmate de tijd verstrijkt, beginnen meer mensen zich aan te melden in uw systeem, omdat u de goedkoopste service op de markt bent en dankzij uw promotie en advertenties. Je begint met het boeken van pakweg 10 boekingen per minuut, en langzaamaan loopt het aantal op naar 20, 30 boekingen per minuut.

Op dit moment realiseert u zich dat het systeem slecht is gaan presteren:de API-latentie is sterk toegenomen, en sommige transacties lopen vast of verhongeren en uiteindelijk mislukken ze. Uw app heeft meer tijd nodig om te reageren, waardoor klanten ontevreden zijn. Wat kunt u doen om het probleem op te lossen?

Patroon 1 - Implementatie query-optimalisatie en verbindingspool:

De eerste oplossing die in gedachten komt, is dat de cache vaak niet-dynamische gegevens gebruikt, zoals boekingsgeschiedenis, betalingsgeschiedenis, gebruikersprofielen enzovoort. Maar na deze applicatielaagcaching kun je het latentieprobleem van API's die dynamische gegevens zoals de huidige chauffeurslocatie of de dichtstbijzijnde taxi's voor een bepaalde klant of de huidige ritkosten op een bepaald moment na het begin van de rit blootleggen, niet oplossen.

U stelt vast dat uw database waarschijnlijk sterk genormaliseerd is, dus introduceert u enkele overbodige kolommen (deze kolommen verschijnen vaak in WHERE of JOIN ON clausule in query's) in veelgebruikte tabellen omwille van denormalisatie. Dit vermindert het aantal join-query's, verdeelt een grote query in meerdere kleinere query's en voegt hun resultaten toe aan de applicatielaag.

Een andere parallelle optimalisatie die u kunt doen, is tweaken rond databaseverbindingen. Databaseclientbibliotheken en externe bibliotheken zijn beschikbaar in bijna alle programmeertalen. U kunt verbindingspoolbibliotheken gebruiken om databaseverbindingen in de cache op te slaan of u kunt de grootte van de verbindingspool configureren in het databasebeheersysteem zelf.

Het maken van een netwerkverbinding is kostbaar omdat het wat heen en weer communicatie tussen client en server vereist. Het poolen van verbindingen kan u helpen het aantal verbindingen te optimaliseren. Verbindingspoolbibliotheken kunnen u helpen om verbindingen te multiplexen - meerdere toepassingsthreads kunnen dezelfde databaseverbinding gebruiken. Ik zal kijken of ik het poolen van verbindingen later in detail kan uitleggen in een apart artikel.

Meet de latentie van uw API's en vind waarschijnlijk 20-50% of meer verminderde latentie. Dit is op dit moment een goede optimalisatie.

Je hebt je bedrijf nu opgeschaald naar nog een stad, meer klanten melden zich aan, je begint langzaam 80-100 boekingen per minuut te doen. Uw systeem kan deze weegschaal niet aan. Wederom zie je dat de API-latentie is toegenomen, de databaselaag het heeft opgegeven, maar deze keer levert geen enkele query-optimalisatie een significante prestatiewinst op. Je controleert de systeemstatistieken, je merkt dat de schijfruimte bijna vol is, de CPU is 80% van de tijd bezet, het RAM-geheugen raakt heel snel vol.

Patroon 2 - Verticaal schalen of omhoog schalen:

Nadat u alle systeemstatistieken heeft onderzocht, weet u dat er geen andere gemakkelijke oplossing is dan het upgraden van de hardware van het systeem. U verhoogt uw RAM-grootte met 2 keer, upgrade schijfruimte met, laten we zeggen, 3 keer of meer. Dit wordt verticale schaling of het opschalen van uw systeem genoemd. U informeert uw infrastructuurteam of devops-team of externe datacenteragenten om uw machine te upgraden.

Maar hoe stel je een machine in voor verticaal schalen?

U wijst een grotere machine toe. Eén benadering is om gegevens niet handmatig van de oude machine te migreren, maar de nieuwe machine in te stellen als replica naar de bestaande machine (primary )-maak een tijdelijke primary replica configuratie. Laat de replicatie op natuurlijke wijze gebeuren. Zodra de replicatie is voltooid, promoveert u de nieuwe machine naar de primaire machine en haalt u de oudere machine offline. Aangezien verwacht wordt dat de grotere machine alle verzoeken zal behandelen, zullen alle lees- en schrijfbewerkingen op deze machine plaatsvinden.

Stoer. Uw systeem is weer up &running met verbeterde prestaties.

Uw bedrijf doet het erg goed en u besluit op te schalen naar nog 3 steden - u bent nu actief in in totaal 5 steden. Verkeer is 3x zo vaak als vroeger, er wordt verwacht dat je zo'n 300 boekingen per minuut doet. Voordat u zelfs maar deze doelboeking bereikt, raakt u opnieuw de prestatiecrisis, de grootte van de database-index neemt sterk toe in het geheugen, het heeft constant onderhoud nodig, het scannen van tabellen met index wordt langzamer dan ooit. U berekent de kosten van het verder opschalen van de machine maar bent niet overtuigd van de kosten. Wat doe je nu?

Patroon 3 - Command Query Responsibility Segregation (CQRS):

U stelt vast dat de grote machine niet alle read/write . aankan verzoeken. In de meeste gevallen heeft elk bedrijf transactiemogelijkheden nodig op write maar niet op read activiteiten. Je vindt het ook prima met een beetje inconsistent of vertraagd read operations &uw bedrijf heeft daar ook geen probleem mee. U ziet een mogelijkheid waarbij het een goede optie kan zijn om de read . te scheiden &write operaties fysiek machinegewijs. Het zal ruimte creëren voor individuele machines om meer read/write te verwerken activiteiten.

Je neemt nu nog twee grote machines en stelt ze in als replica naar de huidige machine. Databasereplicatie zorgt voor het distribueren van gegevens van primary machine naar replica machines. U navigeert door alle leesquery's (Query (Q ) in CQRS ) naar de replica's — elke replica elk leesverzoek kan dienen, navigeert u door alle schrijfquery's (Command (C ) in CQRS ) naar de primary . Er is misschien een kleine vertraging in de replicatie, maar volgens uw zakelijke gebruiksscenario is dat prima.

De meeste middelgrote startups die elke dag een paar honderdduizend verzoeken verwerken, kunnen overleven met een primaire replica, op voorwaarde dat ze periodiek oudere gegevens archiveren.

Nu je schaalt naar nog 2 steden, zie je dat je primary kan niet alle write verwerken verzoeken. Veel write verzoeken hebben latentie. Bovendien is de vertraging tussen primary &replica soms van invloed op klanten en chauffeurs ex - wanneer de reis eindigt, betaalt de klant de chauffeur met succes, maar de chauffeur kan de betaling niet zien omdat de activiteit van de klant een write is verzoek dat naar de primary . gaat , terwijl de activiteit van de bestuurder een read . is verzoek dat naar een van de replica's gaat. Uw algehele systeem is zo traag dat de chauffeur de betaling minstens een halve minuut niet kan zien - frustrerend voor zowel de chauffeur als de klant. Hoe los je het op?

Patroon 4 - Meerdere primaire replicatie

Je hebt heel goed geschaald met primary-replica configuratie, maar nu hebt u meer schrijfprestaties nodig. Je bent misschien klaar om een ​​compromis te sluiten over read prestatie aanvragen. Waarom distribueert u het schrijfverzoek niet naar een replica ook?

In een multi-primary configuratie, kunnen alle machines werken als beide primary &replica . Je kunt denken aan multi-primary zoals een cirkel van machines zegt A->B->C->D->A . B kan gegevens repliceren van A , C kan gegevens repliceren van B , D kan gegevens repliceren van C , A kan gegevens repliceren van D . U kunt gegevens naar elk knooppunt schrijven, terwijl u gegevens leest, kunt u de query naar alle knooppunten uitzenden, wie antwoordt, retourneert dat. Alle knooppunten hebben hetzelfde databaseschema, dezelfde set tabellen, index enz. Dus je moet ervoor zorgen dat er geen botsing is in id over knooppunten in dezelfde tabel, anders zouden tijdens het uitzenden meerdere knooppunten verschillende gegevens retourneren voor dezelfde id .

Over het algemeen is het beter om UUID . te gebruiken of GUID voor idd. Nog een nadeel van deze techniek is — read query's kunnen inefficiënt zijn, omdat het gaat om het uitzenden van een zoekopdracht en het verkrijgen van het juiste resultaat - in feite een benadering voor het verzamelen van spreiding.

Nu schaal je naar nog 5 steden en je systeem heeft weer pijn. Er wordt van u verwacht dat u ongeveer 50 verzoeken per seconde afhandelt. U heeft dringend behoefte aan een groot aantal gelijktijdige verzoeken. Hoe bereik je dat?

Patroon 5 - Partitioneren:

U weet dat uw location database is iets dat high wordt write &read verkeer. Waarschijnlijk write:read verhouding is 7:3 . Dit legt een grote druk op de bestaande databases. De location tabellen bevatten weinig primaire gegevens zoals longitude , latitude , timestamp , driver id , trip id enz. Het heeft niet veel te maken met gebruikersreizen, gebruikersgegevens, betalingsgegevens enz. Hoe zit het met het scheiden van de location tabellen in een apart databaseschema? Hoe zit het met het plaatsen van die database in aparte machines met de juiste primary-replica of multi-primary configuratie?

Dit wordt het partitioneren van gegevens op functionaliteit genoemd. Verschillende databases kunnen gegevens hosten die zijn gecategoriseerd op basis van verschillende functionaliteit, indien nodig kan het resultaat worden geaggregeerd in de back-endlaag. Met behulp van deze techniek kunt u zich concentreren op het goed schalen van die functionaliteiten die veel read/write vereisen verzoeken. Hoewel de back-end of applicatielaag de verantwoordelijkheid moet nemen om de resultaten samen te voegen wanneer dat nodig is, wat waarschijnlijk resulteert in meer codewijzigingen.

Stel je nu voor dat je je bedrijf hebt uitgebreid naar in totaal 20 steden in je land en van plan bent om binnenkort uit te breiden naar Australië. Uw toenemende vraag naar app vereist een snellere en snellere reactie. Geen van de bovenstaande methoden kan je nu tot het uiterste helpen. U moet uw systeem zo schalen dat voor uitbreiding naar andere landen/regio's u niet altijd frequente engineering- of architectuurwijzigingen hoeft uit te voeren. Hoe doe je dat?

Patroon 6 - Horizontaal schalen:

Je googelt veel, leest veel over hoe andere bedrijven het probleem hebben opgelost - en komt tot de conclusie dat je horizontaal moet schalen. Je wijst bijvoorbeeld 50 machines toe - ze hebben allemaal hetzelfde databaseschema dat op zijn beurt dezelfde set tabellen bevat. Alle machines bevatten slechts een deel van de gegevens.

Omdat alle databases dezelfde set tabellen bevatten, kunt u het systeem zo ontwerpen dat de gegevenslocatie er is, d.w.z.; alle gerelateerde gegevens komen op dezelfde machine terecht. Elke machine kan zijn eigen replica's hebben, replica's kunnen worden gebruikt bij foutherstel. Elk van de databases heet shard . Een fysieke machine kan één of meerdere shards hebben - het is aan uw ontwerp hoe u wilt. U moet beslissen over de sharding key op zo'n manier dat een enkele sharding key verwijst altijd naar dezelfde machine. U kunt zich dus veel machines voorstellen die allemaal gerelateerde gegevens in dezelfde set tabellen bevatten, read/write verzoeken voor dezelfde rij of dezelfde set bronnen komen op dezelfde databasemachine terecht.

Sharding is over het algemeen moeilijk - althans dat zeggen ingenieurs van verschillende bedrijven. Maar wanneer u miljoenen of miljarden verzoeken behandelt, moet u zo'n moeilijke beslissing nemen.

Ik zal sharding bespreken in meer detail in mijn volgende bericht, dus ik weerhoud mijn verleiding om meer in dit bericht te bespreken.

Nu u sharding heeft geïnstalleerd, weet u zeker dat u naar veel landen kunt schalen. Uw bedrijf is zo gegroeid dat investeerders u aansporen om het bedrijf over verschillende continenten te schalen. Je ziet hier weer een probleem. API-latentie opnieuw. Uw service wordt gehost in de VS en mensen uit Vietnam hebben het moeilijk om ritten te boeken. Waarom? Wat doe je eraan?

Patroon 7 - Datacenter Wise-partitie:

Uw bedrijf groeit in Amerika, Zuid-Azië en in enkele landen in Europa. U doet dagelijks miljoenen boekingen met miljarden verzoeken die uw server bereiken. Gefeliciteerd - dit is een hoogtepunt voor uw bedrijf.

Maar omdat verzoeken van de app over continenten moeten reizen via honderden of duizenden servers op internet, ontstaat de latentie. Hoe zit het met het verdelen van verkeer over datacenters? U kunt een datacenter in Singapore opzetten dat alle verzoeken uit Zuid-Azië afhandelt, een datacenter in Duitsland kan alle verzoeken uit Europese landen afhandelen en een datacenter in Californië kan alle verzoeken uit de VS afhandelen.

U schakelt ook cross-datacenterreplicatie in, wat helpt bij noodherstel. Dus als het datacenter in Californië replicatie doet naar het datacenter in Singapore, in het geval dat het datacenter in Californië crasht als gevolg van een elektriciteitsprobleem of een natuurramp, kunnen alle Amerikaanse verzoeken terugvallen op het datacenter in Singapore, enzovoort.

Deze schaaltechniek is handig wanneer u miljoenen klanten in verschillende landen moet bedienen en u geen gegevensverlies kunt opvangen, u moet altijd de beschikbaarheid van het systeem behouden.

Dit zijn enkele algemene stapsgewijze technieken voor het schalen van databases. Hoewel de meeste ingenieurs niet genoeg kans krijgen om deze technieken te implementeren, is het als geheel beter om een ​​breder idee te krijgen over zo'n systeem, wat je in de toekomst kan helpen om beter systeem- en architectuurontwerp te doen.

In mijn volgende artikelen zal ik proberen enkele van de concepten in detail te bespreken. Aarzel niet om gepaste feedback te geven voor dit bericht, indien van toepassing.

Het artikel is oorspronkelijk gepubliceerd op het mediumaccount van de auteur:https://medium.com/@kousiknath/understanding-database-scaling-patterns-ac24e5223522



  1. Databaseproxy-failovertijden vergelijken - ProxySQL, MaxScale en HAProxy

  2. Is het mogelijk om meerdere updates uit te voeren met een enkele UPDATE SQL-instructie?

  3. Een Oracle Associative Array gebruiken in een SQL-query

  4. Analytische functies gebruiken in Oracle (Over partitie op trefwoord)