Patroon Sharding

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. Eén server die als host voor het gegevensopslag wordt gehost, kan mogelijk niet de benodigde rekenkracht bieden om deze belasting te ondersteunen, wat resulteert in lange reactietijden voor gebruikers en frequente fouten als toepassingen die proberen een time-out voor gegevens op te slaan en op te halen. Het is mogelijk om geheugen toe te voegen of processors bij te werken, maar het systeem bereikt een limiet wanneer het niet mogelijk is om de rekenbronnen 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 mogelijk tenantgegevens ophalen met behulp van een tenant-id, maar wellicht moeten deze gegevens ook worden opgezocht 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. Let op: er hoeft geen sprake te zijn van een-op-eencorrespondentie tussen shards en de servers waarop deze worden gehost—een enkele 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 toepassing met meerdere tenants 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 geordend 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

Voor een beter begrip van de voordelen van de Hash-strategie boven de andere strategieën, moet u bedenken hoe tenants worden opgeslagen in de gegevensopslag bij een toepassing met meerdere tenants waarin nieuwe tenants opeenvolgend worden geregistreerd. 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:

  • Zoek . 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. Voor een toepassing met meerdere tenants geldt bijvoorbeeld:

  • 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.

  • Aan tenants met hoge waarde kunnen afzonderlijke licht beladen shards met hoge prestaties worden toegewezen, terwijl tenants met minder waarde worden verwacht meer dichtbevolkte, drukkere 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 automatische-toenamevelden niet worden gecoördineerd in verschillende shards. Dit kan ertoe leiden dat items in verschillende shards dezelfde shardsleutel hebben.

    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 Designing Partitions for Scalability (Partities ontwerpen voor schaalbaarheid) in Data Partitioning Guidance (Handleiding 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.

Voorbeeld

Het volgende voorbeeld in C# maakt gebruikt van een set SQL Server-databases die als shards fungeren. Elke database bevat een subset van de gegevens die worden gebruikt voor een toepassing. Met de toepassing worden gegevens opgehaald die zijn verdeeld over de shards met behulp van de eigen shardinglogica (dit is een voorbeeld van een fanout-query). De details van de gegevens in elke shard worden geretourneerd met behulp van een methode genaamd GetShards. Met deze methode wordt een overzichtslijst met ShardInformation-objecten geretourneerd, waarbij het type ShardInformation een id voor elke shard en de SQL Server-verbindingsreeks bevat die een toepassing nodig heeft om verbinding te maken met de shard (de verbindingsreeksen worden niet weergegeven in het codevoorbeeld).

private IEnumerable<ShardInformation> GetShards()
{
  // This retrieves the connection information from a shard store
  // (commonly a root database).
  return new[]
  {
    new ShardInformation
    {
      Id = 1,
      ConnectionString = ...
    },
    new ShardInformation
    {
      Id = 2,
      ConnectionString = ...
    }
  };
}

De code hieronder laat zien hoe de toepassing gebruikmaakt van de lijst met ShardInformation objecten om een query uit te voeren waarmee gegevens parallel worden opgehaald uit elke shard. De details van de query worden niet weergegeven, maar in dit voorbeeld bevatten de opgehaalde gegevens een tekenreeks die informatie kan bevatten, zoals de naam van een klant als de shards de gegevens van klanten bevatten. De resultaten worden samengevoegd in een ConcurrentBag-verzameling die wordt verwerkt in de toepassing.

// Retrieve the shards as a ShardInformation[] instance.
var shards = GetShards();

var results = new ConcurrentBag<string>();

// Execute the query against each shard in the shard list.
// This list would typically be retrieved from configuration
// or from a root/primary shard store.
Parallel.ForEach(shards, shard =>
{
  // NOTE: Transient fault handling isn't included,
  // but should be incorporated when used in a real world application.
  using (var con = new SqlConnection(shard.ConnectionString))
  {
    con.Open();
    var cmd = new SqlCommand("SELECT ... FROM ...", con);

    Trace.TraceInformation("Executing command against shard: {0}", shard.Id);

    var reader = cmd.ExecuteReader();
    // Read the results in to a thread-safe data structure.
    while (reader.Read())
    {
      results.Add(reader.GetString(0));
    }
  }
});

Trace.TraceInformation("Fanout query complete - Record Count: {0}",
                        results.Count);

Volgende stappen

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

  • Gegevensconsistentie-primer. 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 kunnen ook relevant zijn bij het implementeren van dit patroon:

  • Indextabelpatroon. 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.
  • Materialized View-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.