Patroon Sharding

Azure SQL Database
Azure Cosmos DB

Een gegevensarchief onderverdelen in een set met horizontale partities of shards. Dit kan de schaalbaarheid verbeteren bij het opslaan en openen van grote hoeveelheden gegevens.

Context en probleem

Een gegevensopslag die wordt gehost op een enkele server, kan te maken krijgen met de volgende beperkingen:

  • Opslagruimte. Een gegevensopslag voor een grootschalige cloudtoepassing moet een grote hoeveelheid gegevens kunnen bevatten die mettertijd nog aanzienlijk kan toenemen. Een server heeft doorgaans een eindige hoeveelheid schijfruimte, maar u kunt bestaande schijven vervangen door grotere schijven, of extra schijven aan een computer toevoegen naarmate de hoeveelheid gegevens groeit. Het systeem bereikt uiteindelijk echter een limiet waarboven de opslagcapaciteit van een bepaalde server niet meer eenvoudig kan worden verhoogd.

  • Rekenresources. Een cloudtoepassing moet ondersteuning kunnen bieden aan een groot aantal gelijktijdige gebruikers, die allemaal informatie uit de gegevensopslag ophalen door query’s uit te voeren. Een enkele server die als host fungeert voor het gegevensarchief, kan mogelijk niet de benodigde rekenkracht bieden om deze belasting te ondersteunen, wat resulteert in langere reactietijden voor gebruikers en frequente fouten wanneer toepassingen proberen om een time-out voor gegevens op te slaan en op te halen. Het is mogelijk om geheugen of upgradeprocessors toe te voegen, maar het systeem bereikt een limiet wanneer het niet mogelijk is om de rekenresources verder te verhogen.

  • Netwerkbandbreedte. De prestaties van een gegevensopslag die wordt uitgevoerd op een enkele server, zijn uiteindelijk afhankelijk van de snelheid waarmee de server aanvragen kan ontvangen en antwoorden kan verzenden. Het kan voorkomen dat de hoeveelheid netwerkverkeer de capaciteit overschrijdt van het netwerk dat wordt gebruikt om verbinding te maken met de server, wat resulteert in mislukte aanvragen.

  • Geografie. Het kan noodzakelijk zijn om gegevens die zijn gegenereerd door een specifieke gebruiker, op te slaan in dezelfde regio als deze gebruiker. Dit is om juridische redenen, of om nalevings- of prestatieredenen, of om de latentie van de gegevenstoegang te verminderen. Als gebruikers zijn verspreid over verschillende landen of regio’s, is het misschien niet mogelijk om alle gegevens voor de toepassing op te slaan in één gegevensopslag.

Als u verticaal schaalt door meer schijfcapaciteit, verwerkingskracht, geheugen en netwerkverbindingen toe te voegen, kan het effect van een aantal van deze beperkingen worden uitgesteld, maar dit is waarschijnlijk maar een tijdelijke oplossing. Een commerciële cloudtoepassing die heel veel gebruikers en grote hoeveelheden gegevens kan ondersteunen, kan nagenoeg oneindig worden geschaald. Verticaal schalen is daarom niet noodzakelijkerwijs de beste oplossing.

Oplossing

Verdeel de gegevensopslag in horizontale partities of shards. Elke shard heeft hetzelfde schema, maar bevat een eigen unieke subset met gegevens. Een shard is een gegevensopslag op zichzelf (deze kan de gegevens van vele entiteiten van verschillende typen bevatten) en wordt uitgevoerd op een server die fungeert als opslagknooppunt.

Dit patroon biedt de volgende voordelen:

  • U kunt het systeem uitschalen door extra shards toe te voegen die worden uitgevoerd op extra opslagknooppunten.

  • Een systeem kan gebruikmaken van gebruiksklare hardware in plaats van gespecialiseerde en dure computers te gebruiken voor elk opslagknooppunt.

  • U kunt het aantal conflicten verminderen en de prestaties verbeteren door de workload over verschillende shards te verdelen.

  • In de cloud kunnen shards zich fysiek dicht bij de gebruikers bevinden die de gegevens gaan opvragen.

Wanneer u een gegevensopslag onderverdeelt in shards, moet u bepalen welke gegevens in elke shard moeten worden geplaatst. Een shard bevat meestal items die binnen een opgegeven bereik vallen, bepaald door een of meer kenmerken van de gegevens. Deze kenmerken vormen de shardsleutel (ook wel aangeduid als de partitiesleutel). De shardsleutel moet statisch zijn. Deze mag niet zijn gebaseerd op gegevens die kunnen veranderen.

Met sharding worden de gegevens fysiek gerangschikt. Wanneer gegevens met een toepassing worden opgeslagen en opgehaald, wordt de toepassing op basis van de shardinglogica naar de juiste shard geleid. Deze shardinglogica kan worden geïmplementeerd als onderdeel van de toegangscode voor de gegevens in de toepassing, of kan worden geïmplementeerd met het gegevensopslagsysteem als dit systeem sharding transparant ondersteunt.

Door de fysieke locatie van de gegevens af te leiden in de shardinglogica is er sprake van een hoge mate van controle over welke shards welke gegevens bevatten. Het biedt ook de mogelijkheid om gegevens te migreren tussen shards zonder dat de bedrijfslogica van een toepassing opnieuw moet worden uitgevoerd, als de gegevens in de shards later opnieuw moeten worden verdeeld (bijvoorbeeld als de shards niet in evenwicht zijn). Een afweging is de extra overhead voor gegevenstoegang die is vereist bij het bepalen van de locatie van elk gegevensitem terwijl het wordt opgehaald.

Voor optimale prestaties en schaalbaarheid is het belangrijk om de gegevens op te splitsen op een manier die juist is voor de typen query’s die worden uitgevoerd met de toepassing. In veel gevallen is het onwaarschijnlijk dat het shardingschema exact overeenkomt met de vereisten van elke query. In een systeem met meerdere tenants moet een toepassing bijvoorbeeld tenantgegevens ophalen met behulp van de tenant-id, maar moet deze gegevens mogelijk ook worden opgezoekd op basis van een ander kenmerk, zoals de naam of locatie van de tenant. Implementeer in deze gevallen een shardingstrategie met een shardsleutel die ondersteuning biedt voor de meest uitgevoerde query’s.

Als met query’s regelmatig gegevens worden opgehaald op basis van een combinatie van kenmerken, kunt u waarschijnlijk een samengestelde shardsleutel definiëren door kenmerken aan elkaar te koppelen. U kunt ook een patroon zoals Indextabel gebruiken om gegevens snel te kunnen opzoeken op basis van kenmerken die niet zijn gekoppeld aan de shardsleutel.

Shardingstrategieën

Er zijn drie strategieën die vaak worden gebruikt bij het selecteren van de shardsleutel en het bepalen hoe u gegevens wilt verdelen over shards. Houd er rekening mee dat er geen een-op-een-correspondentie hoeft te zijn tussen shards en de servers die deze hosten. Eén server kan meerdere shards hosten. De strategieën zijn:

De strategie: Opzoeken. In deze strategie wordt met de shardinglogica een toewijzing geïmplementeerd die met behulp van de shardsleutel een aanvraag voor gegevens routeert naar de shard die deze gegevens bevat. In een multitenant-toepassing kunnen alle gegevens voor een tenant samen worden opgeslagen in een shard met behulp van de tenant-id als de shardsleutel. Meerdere tenants kunnen dezelfde shard delen, maar de gegevens voor een enkele tenant worden niet over meerdere shards verspreid. De afbeelding illustreert sharding van tenantgegevens op basis van de tenant-id's.

Afbeelding 1: sharding van tenantgegevens op basis van de tenant-id's

De toewijzing tussen de shardsleutel en de fysieke opslag kan zijn gebaseerd op fysieke shards waarbij elke shardsleutel is toegewezen aan een fysieke partitie. Een andere flexibelere techniek voor de herverdeling van shards is virtuele partitionering, waarbij shardsleutels zijn toegewezen aan een aantal virtuele shards, die elk weer zijn toegewezen aan een kleiner aantal fysieke partities. Bij deze methode worden met een toepassing gegevens gevonden met behulp van een shardsleutel die verwijst naar een virtuele shard. Er worden op een transparante manier virtuele shards toegewezen een fysieke partities. De toewijzing tussen een virtuele shard en een fysieke partitie kan worden gewijzigd zonder dat de toepassingscode hoeft te worden aangepast voor het gebruik van een andere set shardsleutels.

De strategie: Bereik. Met deze strategie worden gerelateerde items gegroepeerd in dezelfde shard en gesorteerd op shardsleutel. De shardsleutels zijn opeenvolgend. Dit is handig voor toepassingen waarmee vaak sets met items worden opgehaald met behulp van bereikquery’s (query’s die een set gegevensitems retourneren voor een shardsleutel die binnen een bepaald bereik valt). Als een toepassing bijvoorbeeld regelmatig alle bestellingen moet zoeken die in een opgegeven maand zijn geplaatst, kunnen deze gegevens sneller worden opgehaald als alle bestellingen voor een maand in dezelfde shard zijn opgeslagen in de volgorde datum/tijd. Als elke bestelling is opgeslagen in een andere shard, moeten ze afzonderlijk worden opgehaald door een groot aantal point-query’s uit te voeren (dat zijn query’s die een enkel gegevensitem retourneren). De volgende afbeelding illustreert het opslaan van opeenvolgende gegevenssets (bereiken) in de shard.

Afbeelding 2 - Opeenvolgende gegevenssets (bereiken) opslaan in shards

In dit voorbeeld is de shardsleutel een samengestelde sleutel waarin de maand van de bestelling het belangrijkste onderdeel is, gevolgd door de dag en tijd van de bestelling. De gegevens voor bestellingen worden automatisch geordend wanneer nieuwe bestellingen worden gemaakt en toegevoegd aan een shard. Soms biedt een gegevensopslag ondersteuning voor tweeledige shardsleutels. Deze bestaan uit een partitiesleutel waarmee de shard wordt geïdentificeerd, en een rijsleutel waarmee een uniek item in de shard wordt geïdentificeerd. Gegevens worden meestal in rijvolgorde opgeslagen in de shard. Items die zijn onderworpen aan bereikquery's en moeten worden gegroepeerd, kunnen gebruikmaken van een shardsleutel met dezelfde waarde voor de partitiesleutel maar een unieke waarde voor de rijsleutel.

De strategie: Hash. Het doel van deze strategie is om de kans op hotspots (shards die een te groot aantal werkbelastingen ontvangen) te verminderen. De gegevens worden zo verdeeld over de shards dat er een goed evenwicht bestaat tussen de grootte van elke shard en de gemiddelde belasting waar elke shard mee te maken krijgt. Items worden met behulp van shardinglogica opgeslagen in de shard op basis van een hash met een of meer kenmerken van de gegevens. Met de gekozen hash behoren de gegevens evenwichtig te worden verdeeld over de shards, mogelijk door een willekeurig element te introduceren in de berekening. De volgende afbeelding illustreert sharding van tenantgegevens op basis van een hash met tenant-id's.

Afbeelding 3: sharding van tenantgegevens op basis van een hash met tenant-id's

Als u inzicht wilt krijgen in het voordeel van de Hash-strategie ten opzichte van andere shardingstrategieën, kunt u overwegen hoe een multitenant-toepassing die nieuwe tenants opeenvolgend registreert, de tenants kan toewijzen aan shards in het gegevensarchief. Wanneer u een Bereik-strategie gebruikt, worden de gegevens voor de tenants 1 tot en met n opgeslagen in shard A, de gegevens voor tenants n+1 in shard B, enzovoort. Als de meest recent geregistreerde tenants ook het meest actief zijn, vinden de meeste gegevensactiviteiten plaats in een klein aantal shards, wat hotspots kan veroorzaken. Met de Hash-strategie, daarentegen, worden tenants toegewezen aan shards op basis van een hash met de bijbehorende tenant-id’s. Dit betekent dat opeenvolgende tenants waarschijnlijk worden toegewezen aan verschillende shards. Op deze manier wordt de werkbelasting dus over de shards verdeeld. In de vorige afbeelding wordt dit weergegeven voor tenant 55 en 56.

De drie shardingstrategieën hebben de volgende voordelen en overwegingen:

  • Opzoeken. Dit biedt meer controle over de manier waarop shards worden geconfigureerd en gebruikt. Het gebruik van virtuele shards vermindert de gevolgen van het herverdelen van gegevens, omdat er nieuwe fysieke partities kunnen worden toegevoegd om de workload beter te verdelen. De toewijzing tussen een virtuele shard en de fysieke partities waarmee de shard is geïmplementeerd, kunnen worden gewijzigd zonder dat dit de toepassingscode beïnvloedt die gebruikmaakt van een shardsleutel om gegevens op te slaan en op te halen. Het opzoeken van shardlocaties kan zorgen voor extra overhead.

  • Bereik. Dit is eenvoudig te implementeren en werkt goed met bereikquery’s omdat vaak in één bewerking meerdere gegevensitems kunnen worden opgehaald uit een enkele shard. Deze strategie biedt eenvoudiger gegevensbeheer. Als gebruikers uit dezelfde regio zich bijvoorbeeld in dezelfde shard bevinden, kunnen in elke tijdzone updates worden gepland op basis van de lokale belasting en het lokale eisenpatroon. Deze strategie biedt echter geen optimale balans tussen shards. Het herverdelen van shards is lastig en het probleem van de onevenwichtig verdeelde belasting wordt er mogelijk niet mee opgelost als het merendeel van de activiteiten is bestemd voor aangrenzende shardsleutels.

  • Hash. Deze strategie biedt een grotere kans op een gelijke verdeling van gegevens en belasting. Aangevraagde routering kan direct worden uitgevoerd met behulp van de hashfunctie. Er hoeft geen toewijzing te worden onderhouden. Let op: berekenen van de hash kan zorgen voor extra overhead. Bovendien is het herverdelen van shards lastig.

In de meeste shardingsystemen worden een of meer van de hierboven beschreven methoden geïmplementeerd, maar kijk ook naar de bedrijfsbehoeften en het gegevensgebruik van uw toepassingen. Bijvoorbeeld in een toepassing met meerdere tenants:

  • U kunt gegevens opslaan in een shard op basis van workload. U kunt de gegevens voor zeer vluchtige tenants scheiden in afzonderlijke shards. De snelheid van toegang tot gegevens voor andere tenants wordt als gevolg hiervan mogelijk verbeterd.

  • U kunt gegevens opslaan in een shard op basis van de locatie van tenants. U kunt de gegevens voor tenants in een specifieke geografische locatie gedurende de daluren in de betreffende regio offline halen voor het maken van back-ups en voor onderhoud. De gegevens voor tenants in andere regio’s blijven in deze periode online en toegankelijk tijdens werkuren.

  • Tenants met een hoge waarde kunnen hun eigen privé-, krachtige, licht geladen shards toewijzen, terwijl tenants met een lagere waarde naar verwachting dichter verpakte, drukke shards delen.

  • De gegevens voor tenants die een hoge mate van gegevensisolatie en privacy nodig hebben, kunnen worden opgeslagen op een volledig afzonderlijke server.

Bewerkingen voor schalen en verplaatsen

Elke shardingstrategie biedt andere mogelijkheden en complexiteitsniveaus voor inschalen, uitschalen, het verplaatsen van gegevens en het onderhouden van de status.

In de Lookup-strategie kunnen bewerkingen voor schalen en verplaatsen worden uitgevoerd op gebruikersniveau, hetzij online of offline. De techniek is om bepaalde of alle gebruikersactiviteiten op te schorten (bijvoorbeeld tijdens daluren), de gegevens te verplaatsen naar de nieuwe virtuele partitie of fysieke shard, de toewijzingen te wijzigen, eventuele caches met deze gegevens ongeldig te maken of te vernieuwen, en de gebruikersactiviteiten vervolgens te laten hervatten. Dit type bewerking kan vaak centraal worden beheerd. Voor de Lookup-strategie moeten opslaan in een cache en replicatie mogelijk zijn.

De Bereik-strategie legt een aantal beperkingen op aan het schalen en verplaatsen van gegevens, wat gewoonlijk moet worden uitgevoerd wanneer de gegevensopslag geheel of gedeeltelijk offline is, omdat de gegevens moeten worden opgesplitst en samengevoegd in verschillende shards. Het probleem van onevenwichtig verdeelde belasting wordt mogelijk niet opgelost door de gegevens te verplaatsen voor herverdeling van de shards, als het merendeel van de activiteiten is bestemd voor aangrenzende shardsleutels of gegevens-id’s binnen hetzelfde bereik. Voor de Bereik-strategie is mogelijk ook vereist dat een bepaalde status wordt onderhouden om bereiken toe te wijzen aan de fysieke partities.

Met de Hash-strategie wordt schalen en verplaatsen complexer omdat de partitiesleutels hashes zijn met de shardsleutels of gegevens-id’s. De nieuwe locatie van elke shard moet worden bepaald via de hashfunctie, of de functie moet worden aangepast om de juiste toewijzingen op te geven. Voor de Hash-strategie is onderhoud van de status niet vereist.

Problemen en overwegingen

Beschouw de volgende punten als u besluit hoe u dit patroon wilt implementeren:

  • Sharding is een aanvulling op andere vormen van partitionering, zoals verticale partitionering en functionele partitionering. Een enkele shard kan bijvoorbeeld entiteiten bevatten die verticaal zijn gepartitioneerd, en er kan een functionele partitie worden geïmplementeerd als meerdere shards. Zie Data Partitioning Guidance (Handleiding voor gegevenspartitionering) voor meer informatie over partitioneren.

  • Houd shards in evenwicht zodat ze allemaal dezelfde hoeveelheid I/O verwerken. Aangezien gegevens worden ingevoegd en verwijderd, is het noodzakelijk om de shards periodiek te herverdelen om een gelijke verdeling te garanderen en de kans op hotspots te verminderen. Herverdelen kan een kostbare zaak zijn. Als u de noodzaak voor herverdeling wilt verminderen, moet u groei inplannen door ervoor te zorgen dat elke shard voldoende vrije ruimte heeft om de verwachte hoeveelheid wijzigingen te verwerken. U moet ook strategieën en scripts ontwikkelen die u kunt gebruiken om shards snel te herverdelen als dit nodig is.

  • Gebruik stabiele gegevens voor de shardsleutel. Als de shardsleutel wordt gewijzigd, moeten de bijbehorende gegevens mogelijk worden verplaatst tussen shards, wat het aantal updatebewerkingen doet toenemen. Baseer om deze reden de shardsleutel niet op potentieel vluchtige gegevens. Zoek in plaats hiervan naar kenmerken die onveranderlijk zijn of die op een natuurlijke manier een sleutel vormen.

  • Zorg ervoor dat de shardsleutels uniek zijn. Gebruik bijvoorbeeld geen automatische-toenamevelden als shardsleutel. In sommige systemen kunnen automatisch gegenereerde velden niet worden gecoördineerd tussen shards, wat mogelijk resulteert in items in verschillende shards met dezelfde shardsleutel.

    Automatische-toenamewaarden in andere velden die geen shardsleutels zijn, kunnen ook problemen veroorzaken. Als u bijvoorbeeld automatische-toenamevelden gebruikt om unieke id’s te genereren, kan aan twee verschillende items uit verschillende shards dezelfde id worden toegewezen.

  • Het is misschien niet mogelijk om een shardsleutel te ontwerpen die overeenkomt met de vereisten van elke mogelijke query die kan worden uitgevoerd op de gegevens. Plaats de gegevens in shards om ondersteuning te bieden voor de meest gebruikte query’s. Maak daarnaast, indien nodig, secundaire indextabellen om ondersteuning te bieden voor query’s waarmee gegevens worden opgehaald met criteria die zijn gebaseerd op kenmerken die geen onderdeel uitmaken van de shardsleutel. Zie Patroon Indextabel voor meer informatie.

  • Query’s die maar op één shard worden uitgevoerd, zijn efficiënter dan query’s waarmee gegevens uit meerdere shards worden opgehaald. Vermijd daarom de implementatie van een shardingsysteem die ertoe leidt dat met toepassingen grote hoeveelheden query’s worden uitgevoerd die gegevens samenvoegen in verschillende shards. Onthoud: een enkele shard kan de gegevens voor meerdere typen entiteiten bevatten. Overweeg om uw gegevens te denormaliseren om gerelateerde entiteiten waarnaar vaak wordt gezocht (zoals de gegevens van klanten en de bestellingen die ze hebben geplaatst), bij elkaar te bewaren in dezelfde shard en zo het aantal afzonderlijke leesbewerkingen te verminderen dat met een toepassing moet worden uitgevoerd.

    Als een entiteit in één shard verwijst naar een entiteit die is opgeslagen in een andere shard, neemt u de shardsleutel voor de tweede entiteit op als onderdeel van het schema voor de eerste entiteit. Dit kan helpen om de prestaties te verbeteren van query’s die verwijzen naar gerelateerde gegevens in verschillende shards.

  • Als met een toepassing query’s moeten worden uitgevoerd waarmee gegevens worden opgehaald uit verschillende shards, kunnen deze gegevens wellicht worden opgehaald met behulp van parallelle taken. Een voorbeeld hiervan zijn fanout-query’s waarbij gegevens uit meerdere shards parallel worden opgehaald en vervolgens worden samengevoegd in één resultaat. Met deze methode wordt echter onvermijdelijk enige complexiteit toegevoegd aan de toegangslogica voor de gegevens van een oplossing.

  • Voor veel toepassingen is het efficiënter om grote aantallen kleine shards te maken dan om een klein aantal grote shards te hebben, omdat de kleine shards betere mogelijkheden bieden voor load balancing. Dit kan ook nuttig zijn als u verwacht dat u later shards van één fysieke locatie moet migreren naar een andere. Een kleine shard kan sneller worden verplaatst dan een grote.

  • Zorg ervoor dat de beschikbare resources voor elk shardopslagknooppunt voldoende zijn voor het afhandelen van de vereisten voor de schaalbaarheid wat betreft de omvang en doorvoer van gegevens. Zie de sectie Partities ontwerpen voor schaalbaarheid in de richtlijnen voor gegevenspartitionering voor meer informatie.

  • Overweeg om de verwijzingsgegevens te repliceren naar alle shards. Als een bewerking waarmee gegevens worden opgehaald uit een shard, als onderdeel van dezelfde query ook verwijst naar statische of langzaam verplaatsende gegevens, voegt u deze gegevens toe aan de shard. Alle gegevens voor de query kunnen vervolgens eenvoudig worden opgehaald met de toepassing, zonder dat de gegevensopslag nog een keer hoeft te worden bezocht.

    Als verwijzingsgegevens die in meerdere shards zijn opgeslagen, worden gewijzigd, moeten deze wijzigingen in het systeem in alle shards worden gewijzigd. Tijdens deze synchronisatie kan een zekere mate van inconsistentie optreden in het systeem. Als u dit doet, moet u ervoor zorgen dat uw toepassingen dit kunnen verwerken.

  • Het kan lastig zijn om referentiële integriteit en consistentie tussen shards te waarborgen. Voer daarom zo min mogelijk bewerkingen uit die van invloed zijn op gegevens in meerdere shards. Als met een toepassing gegevens in verschillende shards moeten worden gewijzigd, moet u evalueren of volledige consistentie van de gegevens daadwerkelijk is vereist. In plaats daarvan is het implementeren van uiteindelijke consistentie een gebruikelijke aanpak in de cloud. De gegevens in elke partitie worden afzonderlijk bijgewerkt. De toepassingslogica is verantwoordelijk voor het voltooien van de updates en het verwerken van de inconsistenties die kunnen optreden wanneer naar gegevens wordt gezocht terwijl een uiteindelijk consistente bewerking wordt uitgevoerd. Zie Inleiding over gegevensconsistentie voor meer informatie over het implementeren van uiteindelijke consistentie.

  • Het configureren en beheren van een groot aantal shards kan een uitdaging vormen. Taken zoals bewaken, back-ups maken, controleren op consistentie, en logboekregistratie of controle, moeten worden uitgevoerd op meerdere shards en servers die zich op verschillende locaties kunnen bevinden. Deze taken worden waarschijnlijk geïmplementeerd met behulp van scripts of andere automation-oplossingen, maar de kans is groot dat er toch nog extra beheervereisten zijn.

  • Shards kunnen naar bepaalde geografische locaties worden verplaatst zodat de gegevens die ze bevatten, zich dichtbij de instanties van een toepassing bevinden waarin ze worden gebruikt. Deze methode kan de prestaties aanzienlijk verbeteren, maar vereist extra aandacht voor taken die toegang nodig hebben tot meerdere shards in verschillende locaties.

Wanneer dit patroon gebruiken

Gebruik dit patroon wanneer de benodigde schaling voor een gegevensopslag waarschijnlijk de beschikbare resources voor een enkel opslagknooppunt overschrijdt, of wanneer de prestaties moeten worden verbeterd door het aantal conflicten in een gegevensopslag te verminderen.

Notitie

Sharding richt zich voornamelijk op het verbeteren van de prestaties en schaalbaarheid van een systeem, maar als neveneffect kan het ook de beschikbaarheid verbeteren door de verdeling van de gegevens in afzonderlijke partities. Een fout in een van de partities leidt er niet noodzakelijkerwijs toe dat een toepassing geen toegang meer heeft tot de gegevens in andere partities, en een operator kan onderhoud of herstel uitvoeren voor een of meer partities zonder dat alle gegevens voor een toepassing ontoegankelijk worden. Zie Data Partitioning Guidance (Handleiding voor gegevenspartitionering) voor meer informatie.

Workloadontwerp

Een architect moet evalueren hoe het Sharding-patroon kan worden gebruikt in het ontwerp van hun workload om de doelstellingen en principes te verhelpen die worden behandeld in de pijlers van het Azure Well-Architected Framework. Voorbeeld:

Pijler Hoe dit patroon ondersteuning biedt voor pijlerdoelen
Beslissingen over betrouwbaarheidsontwerp helpen uw workload bestand te worden tegen storingen en ervoor te zorgen dat deze herstelt naar een volledig functionerende status nadat er een fout is opgetreden. Omdat de gegevens of verwerking is geïsoleerd voor de shard, blijft een storing in één shard geïsoleerd voor die shard.

- RE:06 Gegevenspartitionering
- RE:07 Zelfbehoud
Kostenoptimalisatie is gericht op het ondersteunen en verbeteren van het rendement van uw workload op investering. Een systeem dat shards implementeert, profiteert vaak van het gebruik van meerdere exemplaren van goedkopere reken- of opslagresources in plaats van één duurdere resource. In veel gevallen kan deze configuratie u geld besparen.

- CO:07 Componentkosten
Prestatie-efficiëntie helpt uw workload efficiënt te voldoen aan de vereisten door optimalisaties in schalen, gegevens, code. Wanneer u sharding gebruikt in uw schaalstrategie, worden de gegevens of verwerking geïsoleerd van een shard, zodat deze alleen concurreren voor resources met andere aanvragen die naar die shard worden omgeleid. U kunt ook sharding gebruiken om te optimaliseren op basis van geografie.

- PE:05 Schalen en partitioneren
- PE:08 Gegevensprestaties

Net als bij elke ontwerpbeslissing moet u rekening houden met eventuele compromissen ten opzichte van de doelstellingen van de andere pijlers die met dit patroon kunnen worden geïntroduceerd.

Opmerking

Overweeg een website die een uitgebreide verzameling informatie over gepubliceerde boeken wereldwijd weergeeft. Het aantal mogelijke boeken in deze workload en de typische query-/gebruikspatronen geven het gebruik van één relationele database aan om de boekgegevens op te slaan. De workloadarchitect besluit om de gegevens over meerdere database-exemplaren te sharden met behulp van het statische ISBN (International Standard Book Number) van de boeken voor de shardsleutel. In het bijzonder gebruiken ze het controlecijfer (0 - 10) van het ISBN, omdat ze 11 mogelijke logische shards geven en de gegevens redelijk verdeeld zijn over elke shard. Om te beginnen besluiten ze de 11 logische shards in drie fysieke sharddatabases op te slaan. Ze gebruiken de zoek-sharding-benadering en slaan de sleutel-naar-server-toewijzingsgegevens op in een shard-toewijzingsdatabase.

Diagram met een Azure-app Service, vier Azure SQL Databases en één Azure AI Search.

Diagram met een Azure-app Service met het label 'Book catalog website' die is verbonden met meerdere Azure SQL Database-exemplaren en een Azure AI Search-exemplaar. Een van de databases is gelabeld als de ShardMap-database en heeft een voorbeeldtabel die een deel van de toewijzingstabel weerspiegelt die ook verder in dit document wordt vermeld. Er worden ook drie exemplaren van sharddatabases vermeld: bookdbshard0, bookdbshard1 en bookdbshard2. Elk van de databases bevat een voorbeeld van een lijst met tabellen eronder. Alle drie de voorbeelden zijn identiek, met de tabellen 'Books' en 'LibraryOfCongressCatalog' en een indicator van meer tabellen. Het pictogram Azure AI Search geeft aan dat het wordt gebruikt voor facetnavigatie en sitezoekopdrachten. Beheerde identiteit wordt weergegeven die is gekoppeld aan de Azure-app Service.

Zoek-shard-kaart

De shard-toewijzingsdatabase bevat de volgende shardtoewijzingstabel en -gegevens.

SELECT ShardKey, DatabaseServer
FROM BookDataShardMap
| ShardKey | DatabaseServer |
|----------|----------------|
|        0 | bookdbshard0   |
|        1 | bookdbshard0   |
|        2 | bookdbshard0   |
|        3 | bookdbshard1   |
|        4 | bookdbshard1   |
|        5 | bookdbshard1   |
|        6 | bookdbshard2   |
|        7 | bookdbshard2   |
|        8 | bookdbshard2   |
|        9 | bookdbshard0   |
|       10 | bookdbshard1   |

Voorbeeld van websitecode - toegang tot één shard

De website is niet op de hoogte van het aantal fysieke sharddatabases (drie in dit geval) of de logica waarmee een shardsleutel aan een database-exemplaar wordt toegewezen, maar de website weet wel dat het controlecijfer van de ISBN van een boek als de shardsleutel moet worden beschouwd. De website heeft alleen-lezentoegang tot de shard-toewijzingsdatabase en lees-/schrijftoegang tot alle sharddatabases. In dit voorbeeld gebruikt de website de door het systeem beheerde identiteit van de Azure-app Service die als host fungeert voor de website voor autorisatie om geheimen uit de verbindingsreeks s te houden.

De website is geconfigureerd met de volgende verbindingsreeks s, hetzij in een appsettings.json bestand, zoals in dit voorbeeld, of via App Service-app-instellingen.

{
  ...
  "ConnectionStrings": {
    "ShardMapDb": "Data Source=tcp:<database-server-name>.database.windows.net,1433;Initial Catalog=ShardMap;Authentication=Active Directory Default;App=Book Site v1.5a",
    "BookDbFragment": "Data Source=tcp:SHARD.database.windows.net,1433;Initial Catalog=Books;Authentication=Active Directory Default;App=Book Site v1.5a"
  },
  ...
}

Als er verbindingsgegevens beschikbaar zijn voor de shard-toewijzingsdatabase, ziet een voorbeeld van een updatequery die door de website wordt uitgevoerd naar de database-shardpool van de werkbelasting er ongeveer als volgt uit.

...

// All data for this book is stored in a shard based on the book's ISBN check digit,
// which is converted to an integer 0 - 10 (special value 'X' becomes 10).
int isbnCheckDigit = book.Isbn.CheckDigitAsInt;

// Establish a pooled connection to the database shard for this specific book.
using (SqlConnection sqlConn = await shardedDatabaseConnections.OpenShardConnectionForKeyAsync(key: isbnCheckDigit, cancellationToken))
{
  // Update the book's Library of Congress catalog information
  SqlCommand cmd = sqlConn.CreateCommand();
  cmd.CommandText = @"UPDATE LibraryOfCongressCatalog
                         SET ControlNumber = @lccn,
                             ...
                             Classification = @lcc
                       WHERE BookID = @bookId";

  cmd.Parameters.AddWithValue("@lccn", book.LibraryOfCongress.Lccn);
  ...
  cmd.Parameters.AddWithValue("@lcc", book.LibraryOfCongress.Lcc);
  cmd.Parameters.AddWithValue("@bookId", book.Id);

  await cmd.ExecuteNonQueryAsync(cancellationToken);
}

...

Als in de voorgaande voorbeeldcode book.Isbn 978-8-1130-1024-6 was, moet dit isbnCheckDigit 6 zijn. De aanroep naar OpenShardConnectionForKeyAsync(6) wordt doorgaans geïmplementeerd met een cache-aside-benadering. Er wordt een query uitgevoerd op de shard-toewijzingsdatabase die is geïdentificeerd met de verbindingsreeks ShardMapDb als deze geen shard-gegevens in de cache heeft voor shardsleutel 6. De waarde bookdbshard2 vindt plaats in de verbindingsreeks vanuit de cache van SHARD de toepassing of vanuit de BookDbFragment sharddatabase. Er wordt (opnieuw) een poolverbinding tot stand gebracht voor bookdbshard2.database.windows.net, geopend en geretourneerd naar de aanroepende code. De code werkt vervolgens de bestaande record op dat database-exemplaar bij.

Voorbeeld van websitecode - meerdere shardtoegang

In het zeldzame geval is een directe cross-shard-query vereist voor de website, voert de toepassing een parallelle fan-out-query uit voor alle shards.

...

// Retrieve all shard keys
var shardKeys = shardedDatabaseConnections.GetAllShardKeys();

// Execute the query, in a fan-out style, against each shard in the shard list.
Parallel.ForEachAsync(shardKeys, async (shardKey, cancellationToken) =>
{
  using (SqlConnection sqlConn = await shardedDatabaseConnections.OpenShardConnectionForKeyAsync(key: shardKey, cancellationToken))
  {
    SqlCommand cmd = sqlConn.CreateCommand();
    cmd.CommandText = @"SELECT ...
                          FROM ...
                         WHERE ...";

    SqlDataReader reader = await cmd.ExecuteReaderAsync(cancellationToken);

    while (await reader.ReadAsync(cancellationToken))
    {
      // Read the results in to a thread-safe data structure.
    }

    reader.Close();
  }
});

...

Als alternatief voor shardquery's in deze workload wordt mogelijk een extern onderhouden index gebruikt in Azure AI Search, zoals voor sitezoekopdrachten of facetnavigatiefunctionaliteit.

Shard-exemplaren toevoegen

Het workloadteam is zich ervan bewust dat als de gegevenscatalogus of het gelijktijdige gebruik aanzienlijk groter is dan drie database-exemplaren vereist zijn. Het workloadteam verwacht niet dynamisch databaseservers toe te voegen en zal uitvaltijd van workloads doorstaan als er een nieuwe shard online moet komen. Als u een nieuw shard-exemplaar online brengt, moet u gegevens van bestaande shards naar de nieuwe shard verplaatsen, samen met een update naar de shard-toewijzingstabel. Met deze redelijk statische benadering kan de workload de shardsleuteldatabasetoewijzing in de cache opslaan in de websitecode.

De shardsleutellogica in dit voorbeeld heeft een harde bovengrens van 11 maximale fysieke shards. Als het workloadteam belastingschattingstests uitvoert en evalueert dat er uiteindelijk meer dan 11 databasesexemplaren nodig zijn, moet er een ingrijpende wijziging in de shardsleutellogica worden aangebracht. Deze wijziging omvat de zorgvuldige planning van codewijzigingen en gegevensmigratie naar de nieuwe sleutellogica.

SDK-functionaliteit

In plaats van aangepaste code te schrijven voor shardbeheer en queryroutering naar Azure SQL Database-exemplaren, evalueert u de elastic database-clientbibliotheek. Deze bibliotheek ondersteunt shardtoewijzingsbeheer, gegevensafhankelijke queryroutering en cross-shard-query's in zowel C# als Java.

Volgende stappen

De volgende richtlijnen zijn mogelijk ook relevant bij de implementatie van dit patroon:

  • Inleiding over gegevensconsistentie. Het kan nodig zijn om de consistentie te bewaken voor gegevens die zijn verdeeld over verschillende shards. U vindt hier een overzicht van de problemen rondom het handhaven van de consistentie van gedistribueerde gegevens, evenals een beschrijving van de voor- en nadelen van verschillende consistentiemodellen.
  • Richtlijnen voor gegevenspartitionering. Sharding van een gegevensopslag kan verschillende extra problemen veroorzaken. Hierin worden de problemen beschreven die zijn gerelateerd aan het partitioneren van gegevensopslag in de cloud om de schaalbaarheid te verbeteren, conflicten te verminderen en de prestaties te optimaliseren.

De volgende patronen zijn mogelijk ook relevant bij het implementeren van dit patroon:

  • Indextabel-patroon. Soms is het niet mogelijk om query’s volledig te ondersteunen alleen door het ontwerpen van de shardsleutel. Met dit patroon kunnen met een toepassing snel gegevens worden opgehaald uit een grote gegevensopslag door een andere sleutel op te geven dan de shardsleutel.
  • Gerealiseerde weergave-patroon. Als u de prestaties van bepaalde querybewerkingen wilt bewaken, is het een goed idee om materialized views te maken waarin gegevens woorden samengevoegd en overzichtelijk weergegeven, met name als deze overzichtsgegevens zijn gebaseerd op informatie die is verdeeld over verschillende shards. Dit patroon beschrijft hoe u deze weergaven kunt genereren en vullen.