Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Dela upp ett datalager i en uppsättning horisontella partitioner eller delar. Den här metoden kan förbättra skalbarheten när du lagrar och kommer åt stora mängder data.
Kontext och problem
Ett datalager på en enskild server har följande begränsningar:
Lagringsutrymme: Ett datalager för ett storskaligt molnprogram kan innehålla en stor mängd data som växer med tiden. En server tillhandahåller en begränsad mängd disklagring och du kan ersätta befintliga diskar med större diskar eller lägga till fler diskar när datavolymerna växer. Systemet når så småningom en gräns där du inte kan öka lagringskapaciteten på en enda server.
Beräkningsresurser: Ett molnprogram måste ha stöd för ett stort antal samtidiga användare som varje kör frågor mot datalagret. En enskild server kanske inte ger tillräckligt med databehandlingskraft för den här belastningen, vilket resulterar i utökade svarstider och tidsgränser. Du kan lägga till minne eller uppgradera processorer, men systemet når en gräns där du inte kan öka beräkningsresurserna ytterligare.
Nätverksbandbredd: Den hastighet med vilken en enskild server kan ta emot begäranden och skicka svar begränsar datalagringens prestanda. Nätverkstrafikens volym kan överskrida kapaciteten för nätverksanslutningen, vilket resulterar i misslyckade begäranden.
Geografi: Juridiska krav, efterlevnads- eller prestandakrav kan kräva att du lagrar användardata i samma geografiska region som användarna. Om användarna sträcker sig över länder/regioner kanske du inte kan lagra alla programdata i ett enda datalager.
Om du vill skjuta upp dessa begränsningar tillfälligt kan du skala lodrätt genom att lägga till diskkapacitet, processorkraft, minne och nätverksanslutningar. Ett molnprogram som måste ha stöd för ett stort antal användare och stora datavolymer måste skalas horisontellt.
Lösning
Dela upp datalagret i horisontella partitioner eller shards. Varje shard har samma schema men innehåller sin egen distinkta delmängd av data. Varje shard är ett fullständigt datalager som kan innehålla data för många entiteter av olika typer. En shard körs på en server som fungerar som en lagringsnod.
Det här mönstret har följande fördelar:
Du kan skala ut systemet genom att lägga till fler shards på extra lagringsnoder.
Ett system kan använda inbyggd maskinvara i stället för specialiserade och dyra datorer för varje lagringsnod.
Du kan minska konkurrensen och förbättra prestandan genom att balansera arbetsbelastningen över partitioner.
I molnet kan shards finnas fysiskt nära de användare som har åtkomst till data.
När du delar upp ett datalager i shards bestämmer du vilka data som ska placeras i varje shard. Varje fragment innehåller vanligtvis objekt grupperade efter ett eller flera dataattribut. Dessa attribut utgör shardnyckeln, som ibland kallas för partitionsnyckeln.
Sharding organiserar data fysiskt. När ett program lagrar och hämtar data dirigerar partitioneringslogik den till rätt fragment. Du kan implementera den här logiken i programmets dataåtkomstkod eller i datalagringssystemet om den transparent stöder horisontell partitionering.
Om du abstraherar den fysiska platsen för data i horisontell partitioneringslogik får du kontroll över vilka shards som innehåller vilka data. Du kan också migrera data mellan shards utan att ändra programmets affärslogik när du behöver omdistribuera data, till exempel när shards blir obalanserade. Kompromissen är den extra dataåtkomstkostnaden för att fastställa varje dataobjekts plats vid hämtning.
Shard-nyckelval
Shardnyckeln är det mest kritiska designbeslutet i ett fragmenterat system. Om du vill ändra en shardnyckel när du har valt den måste du vanligtvis migrera alla data till en ny shardlayout, vilket är en dyr och riskabel åtgärd i ett realtidssystem. Fatta det här beslutet noggrant innan du skriver någon kod.
En effektiv shardnyckel är oföränderlig, har hög kardinalitet, distribuerar data och läser in jämnt och överensstämmer med dina dominerande frågemönster så att de flesta begäranden matchas mot en enda shard. Undvik monotont ökande värden (autoincrement-heltal och sekventiella tidsstämplar), attribut med låg kardinalitet (booleska värden och små uppräkningsuppsättningar) och flyktiga attribut som ändras ofta. De här attributen leder till hotspots eller kostsamma dataförflyttningar mellan fragment.
Om inget enskilt attribut uppfyller dessa villkor definierar du en sammansatt shardnyckel genom att kombinera två eller flera attribut. Om frågor måste hämta data efter attribut som inte ingår i shardnyckeln, använd ett mönster, till exempel indextabellmönster, för att tillhandahålla sekundära uppslag.
Mer information om hur du väljer partitionsnycklar mellan Azure-tjänster finns i Vägledning för datapartitionering och strategier för datapartitionering.
Strategier för horisontell partitionering
Använd någon av följande strategier när du väljer shardnyckeln och bestämmer hur du distribuerar data mellan shards. Du behöver ingen en-till-en-korrespondens mellan shards och servrarna som är värdar för dem. En enskild server kan vara värd för flera shards.
Strategi för sökningssharding
I uppslagsstrategin, även kallad katalogbaserad strategi, implementerar horisontell partitioneringslogik en karta som dirigerar en databegäran till fragmentet som innehåller dessa data med hjälp av shardnyckeln. I ett program med flera klienter kan du lagra alla data för en klientorganisation tillsammans i en shard med hjälp av klientorganisations-ID:t som shardnyckel. Flera klientorganisationer kan dela samma shard, men data för en enskild klientorganisation sprids inte över flera shards. Följande diagram visar shardning av hyresgästdata baserat på hyresgäst-ID:n.
Mappningen mellan shardnyckelvärden och fysisk lagring kan vara direkt, där varje shardnyckelvärde mappar till en fysisk partition. En mer flexibel teknik är virtuell partitionering, där shardnyckelvärden mappas till virtuella shards, och systemet mappar sedan dessa virtuella shards till färre fysiska partitioner. Ett program letar upp data med hjälp av ett shardnyckelvärde som refererar till en virtuell shard, och systemet mappar transparent virtuella shards till fysiska partitioner. Mappningen mellan en virtuell shard och en fysisk partition kan ändras utan att programkodändringar krävs.
Strategi för intervallbaserad horisontell partitionering
Den intervallbaserade strategin grupperar relaterade objekt i samma shard och ordnar dem efter sekventiell shardnyckel. Den här strategin stöder program som ofta hämtar uppsättningar med objekt med hjälp av intervallfrågor. Intervallfrågor returnerar en uppsättning dataobjekt för en shardnyckel som ligger inom ett visst intervall.
Om ett program till exempel regelbundet behöver hitta alla beställningar som görs under en viss månad kan du hämta data snabbare om du lagrar alla beställningar för en månad i datum- och tidsordning i samma fragment. Om du lagrar varje beställning i en annan shard måste programmet hämta dem individuellt genom att utföra ett stort antal punktfrågor. Följande diagram visar sekventiella uppsättningar, eller intervall, av data som lagras i shards.
I det här exemplet är shardnyckeln en sammansatt nyckel som innehåller ordermånaden som det mest betydelsefulla elementet följt av orderns dag och tidpunkt. Nya beställningar sorteras naturligt när de skapas och läggs till i en shard.
Vissa datalager stöder tvådelade shardnycklar. En partitionsnyckel identifierar fragmentet och en radnyckel identifierar unikt ett objekt i fragmentet. Fragmentet lagrar vanligtvis data i radnyckelordning. För objekt som behöver intervallfrågor och som måste grupperas tillsammans kan du använda en shardnyckel som har samma värde för partitionsnyckeln men ett unikt värde för radnyckeln.
Hash-baserad horisontell partitioneringsstrategi
Den hash-baserade strategin minskar risken för hotspots, som är shards som får en oproportionerlig mängd belastning. Den här strategin distribuerar data över shards för att balansera storleken på varje shard och den genomsnittliga belastning som varje shard stöter på. Logiken för horisontell partitionering beräknar den shard som ett objekt ska lagras i baserat på en hash för ett eller flera attribut i data. Den valda hashfunktionen bör distribuera data jämnt över skärvorna. Följande diagram visar horisontell partitionering av klientdata baserat på en hash av klient-ID:t.
För att förstå fördelen med hash-strategin jämfört med andra strategier för horisontell partitionering bör du överväga hur ett program med flera klienter som registrerar nya klienter sekventiellt kan tilldela klientorganisationer till shards i datalagret. När du använder intervallstrategin lagras data för klientorganisationer 1 till n i shard A, data för klientorganisationer n+1 till m lagras i shard B och senare klientintervall mappas till efterföljande shards. Om de mest nyligen registrerade klienterna också är de mest aktiva, sker den mesta dataaktiviteten i några delar, vilket kan orsaka flaskhalsar. Däremot allokerar hash-strategin hyresgäster till shards baserat på en hash för deras hyresgäst-ID. Hashen distribuerar vanligtvis sekventiella klienter över olika shards, vilket balanserar belastningen. Det föregående diagrammet visar detta tillvägagångssätt för hyresgästerna 55 och 56.
Strategi för geografisk horisontell partitionering
Den geografiska strategin tilldelar data till datasektioner baserat på det geografiska ursprunget eller den avsedda förbrukningsregionen för dessa datamängder. I många arbetsbelastningar är användare och de data som de genererar koncentrerade till specifika regioner. Regelkrav som lagar om datahemvist kan kräva att specifika data förblir inom en viss jurisdiktion. Även utan regeldrivande faktorer minskar data som placeras nära de användare som har åtkomst till den oftast nätverksfördröjningen för läsningar och skrivningar.
I den här strategin härleder du shardnyckeln från ett geografiskt attribut, till exempel användarens land/region, den ursprungliga datacenterregionen eller en regional klientidentifierare. Du placerar varje shard eller kopplar den till infrastrukturen inom den geografiska gränsen.
Till exempel kan ett program som betjänar kunder i Nordamerika, Europa och Asia-Pacific underhålla tre fragmentgrupper, en grupp i varje motsvarande Azure-region. Ett europeiskt program som endast betjänar europeiska användare skickar en begäran till Europa-shard. Den här metoden minskar svarstiden och uppfyller kraven för datahemvist.
Geografisk horisontell partitionering medför risk för ojämn datadistribution. Om de flesta av dina användare finns i en region medför den regionens shard en oproportionerlig del av belastningen och lagringen. Du kan kombinera geografisk uppdelning med en annan strategi, till exempel hash eller sökning, inom varje region för att fördela belastningen jämnt över flera delar inom samma geografiska gräns.
Fördelar och överväganden för varje strategi
De fyra shardstrategierna har följande fördelar och överväganden:
Uppslagsstrategin ger mer kontroll över shard-konfiguration. Virtuella shards minskar effekten av ombalansering eftersom du kan lägga till nya fysiska partitioner för att balansera arbetsbelastningen. Du kan ändra mappningen mellan en virtuell shard och dess fysiska partitioner utan att påverka programkoden. Att leta upp shardplatser innebär en ökad belastning.
Intervallstrategin är enkel att implementera och fungerar bra med intervallfrågor. Intervallfrågor kan hämta flera dataobjekt från en enda shard i en åtgärd. Datahantering är enklare. Du kan till exempel schemalägga uppdateringar per tidszon baserat på lokala belastningsmönster när användare i samma region delar en shard. Den här strategin balanserar inte belastningen jämnt över skärvor. Rebalansering är svårt och kan kanske inte åtgärda ojämn belastning när majoriteten av aktiviteterna koncentreras på intilliggande shardnycklar.
Hash-strategin ger en bättre chans att jämna ut data och belastningsfördelning. Du kan dirigera begäranden direkt med hjälp av hash-funktionen utan att underhålla en karta. Att beräkna hashen medför en del omkostnader. Ombalansering är svårt utan konsekvent hashning.
Den geografiska strategin uppfyller kraven på datahemlighet och suveränitet som andra strategier inte till sin natur hanterar. Det minskar svarstiden för läsning och skrivning när användare kommer åt data i sin region. Geografisk horisontell partitionering kan dock skapa betydande obalanser i data och belastning när användarpopulationer inte är jämnt fördelade mellan regioner. Frågor som sträcker sig över regioner, till exempel global rapportering, måste hämta data från alla geografiska shards och medföra högre svarstid. Kombinera geografisk horisontell partitionering med en annan strategi i varje region när du behöver både efterlevnad och till och med belastningsfördelning.
De flesta horisontella system implementerar en av dessa metoder, men du bör också tänka på affärskraven för ditt program och dess dataanvändningsmönster. Till exempel i ett program med flera klientorganisationer:
Du kan fragmentera data baserat på arbetsbelastningen. Separera data för mycket volatila klienter i separata shards för att förbättra dataåtkomsthastigheten för andra klienter.
Du kan fragmentera data baserat på hyresgästernas plats. Ta klientdata i en specifik geografisk region offline för säkerhetskopiering och underhåll under den regionens lågtrafiktimmar, medan klientdata i andra regioner förblir online under kontorstid.
Tilldela högt värderade hyresgäster sina egna dedikerade, lätt belastade shardar. Hyresgäster med lägre värde kan dela mer tättpackade shards.
Lagra data för klienter som behöver stark dataisolering och sekretess på separata servrar.
Skalnings- och dataförflyttningsåtgärder för varje strategi
Varje strategi för horisontell partitionering ger olika funktioner och nivåer av komplexitet för att hantera inskalning, utskalning, dataförflyttning och tillståndsunderhåll.
Uppslagsstrategin tillåter skalnings- och dataförflyttningsåtgärder på användarnivå, antingen online eller offline. Så här flyttar du data:
Pausa vissa eller alla användaraktiviteter, vanligtvis under perioder med låg belastning.
Flytta data till den nya virtuella partitionen eller den fysiska skärvan.
Uppdatera mappningarna.
Ogiltigförklara eller uppdatera alla cacheminnen som innehåller dessa data.
Återuppta användaraktiviteten.
Du kan ofta hantera den här åtgärden centralt. Uppslagsstrategin kräver att tillståndet är mycket cachebart och replikvänligt.
Intervallstrategin begränsar skalnings- och dataförflyttningsåtgärder eftersom du måste dela och sammanfoga data mellan shards, vanligtvis när en del av eller hela datalagret är offline. När du flyttar data för att återbalansera shards kanske du inte eliminerar ojämn belastning om de flesta aktiviteter fokuserar på intilliggande shardnycklar eller dataidentifierare inom samma intervall. Intervallstrategin kan också kräva tillstånd för att mappa intervall till fysiska partitioner.
Hash-strategin komplicerar skalnings- och dataförflyttningsåtgärder. Partitionsnycklarna är hashvärden för shardnycklarna eller dataidentifierarna. Med en standard-hash-funktion, till exempel
hash(key) mod N, medför tillägg eller borttagning av en shard-ny omfördelning av de flesta nycklar och utlöser storskalig datamigrering. Konsekvent hashning minskar den här effekten genom att ordna hash-utrymmet så att endast en liten bråkdel av nycklarna flyttas när antalet shard ändras. Hash-strategin kräver inte underhåll av ett separat mappningstillstånd.Den geografiska strategin kopplar direkt skalningsåtgärder till etablering av regional infrastruktur. Att lägga till kapacitet i en region minskar inte belastningen i en annan region. Regelkrav som kräver geografisk horisontell partitionering kan också begränsa dataflytt över geografiska gränser. Inom varje region använder skalning den sekundära strategin som distribuerar data över regionens shardar.
Problem och överväganden
Tänk på följande när du bestämmer hur du ska implementera det här mönstret:
Använd horisontell partitionering som komplement till andra former av partitionering, till exempel vertikal partitionering och funktionell partitionering. Till exempel kan en enskild shard innehålla vertikalt partitionerade entiteter och du kan implementera en funktionell partition som flera shards. Mer information finns i Horisontell, lodrät och funktionell datapartitionering.
Håll shards balanserade så att de alla kan hantera en liknande I/O-volym (input/output). Datasnedvridning ackumuleras över tid när poster infogas och tas bort, vilket leder till hotspots. Planera att balansera om med jämna mellanrum.
Ombalansering flyttar data mellan shards och orsakar ofta stilleståndstid eller minskat dataflöde. Om du vill balansera om mindre ofta använder du virtuella partitioner. Mappa många logiska partitioner till färre fysiska shards. När en shard är överbelastad distribuerar du dess virtuella partitioner till nya fysiska shards utan att omhasha hela datauppsättningen. Azure Cosmos DB använder den här metoden för att frikoppla partitionsschemat från den fysiska infrastrukturen.
Man bör föredra många små fragment framför några stora. Mindre shards migrerar snabbare, balanserar belastningen jämnare och ger större flexibilitet för omdistribution av data.
Använd stabila data för shard-nyckeln. Om shardnyckeln ändras kan du behöva flytta motsvarande dataobjekt mellan shards, vilket ökar kostnaderna för uppdateringsåtgärden. Undvik att basera shard-nyckeln på potentiellt instabil information. Välj attribut som är invarianta eller naturligt bildar en nyckel.
Se till att shardnycklarna är unika. Undvik till exempel att använda fält som ökar automatiskt som shardnyckel. I vissa system kan autoinkrementerade fält inte samordnas mellan shards, vilket kan resultera i att objekt i olika shards har samma shardnyckel.
Anmärkning
Autoinkrementerade värden i andra fält som inte är shard-nycklar kan också orsaka problem. Om du till exempel använder autoinkrementerade fält för att generera unika ID:er kan två olika objekt i olika shards tilldelas samma ID.
Sharda data för att stödja de vanligaste frågorna. Du kanske inte kan utforma en shardnyckel som matchar kraven för varje fråga som görs mot datan. Om det behövs skapar du sekundära indextabeller för att stödja frågor som hämtar data efter attribut som inte ingår i shardnyckeln. Mer information finns i Indextabellmönster.
Utforma din shardnyckel och datamodell så att de flesta åtgärder begränsas till en enda shard. Frågor som endast har åtkomst till en enda shard är effektivare än frågor som hämtar data från flera shards. Avnormalisera dina data för att hålla relaterade entiteter som ofta efterfrågas tillsammans, till exempel kunder och deras beställningar, i samma fragment för att minska antalet separata läsningar.
Frågor mellan partitioner lägger till svarstid, resursförbrukning och komplexitet. När ett program måste hämta data från flera shards använder du parallella utfasningsfrågor som körs mot varje shard samtidigt och aggregerar resultatet. Även med parallellitet avgör den långsammaste shard övergripande svarstiden.
Tips/Råd
Om en entitet i en shard refererar till en entitet i en annan shard tar du med shardnyckeln för den andra entiteten som en del av schemat för den första entiteten. Den här metoden kan förbättra prestandan för frågor som refererar till relaterade data mellan shards.
Överväg att ompröva din fragmentnyckel eller om fragmentering passar dina behov om din arbetsbelastning kräver stark transaktionsintegritet över fragmentgränser. Transaktioner mellan skärvor innebär utmaningar. Distribuerade samordningsprotokoll, till exempel tvåfascommit, lägger till latens, inför fellägen och minskar genomströmningen. De flesta fragmenterade system undviker distribuerade transaktioner och antar eventuell konsistens i stället. I den här modellen uppdateras varje shard separat och programmet hanterar tillfälliga inkonsekvenser.
Kontrollera att de resurser som är tillgängliga för varje shardlagringsnod kan hantera skalbarhetskraven när det gäller datastorlek och dataflöde. Mer information finns i Strategier för datapartitionering.
Överväg att replikera referensdata till alla shards. Om en fråga mot ett shard också refererar till statiska eller långsamma data lägger du till dessa data i shard. Programmet kan sedan hämta alla data för frågan utan att göra en tur och retur till ett separat datalager.
Anmärkning
Om referensdata lagras i flera shards-ändringar måste systemet synkronisera dessa ändringar över alla shards. Viss grad av inkonsekvens kan inträffa medan den här synkroniseringen körs. Utforma dina program så att de tolererar den här inkonsekvensen.
Fragmenterade system multiplicerar driftbelastningen. Planera för dessa problem:
Övervakning: Du måste aggregera mått och loggar över alla shards för att få en fullständig vy över systemets hälsotillstånd.
Säkerhetskopiering och återställning: Du måste säkerhetskopiera varje shard oberoende av varandra och utforma återställningsprocedurer för att upprätthålla korsshardkonsekvens. En återställning av en specifik tidpunkt för en splitter kan skapa inkonsekvenser med andra splitters.
Schemaändringar: Du måste samordna ändringar i datadefinitionsspråket (DDL) för varje shard.
Du kan implementera dessa uppgifter med hjälp av skript eller andra automatiseringslösningar.
Du kan geolokalisera shards för att placera sina data nära de programinstanser som använder dem. Den här metoden kan förbättra prestanda men kräver extra planering för åtgärder som måste komma åt flera shards på olika platser.
När du ska använda det här mönstret
Tips/Råd
Innan du utformar ett anpassat fragmenteringslager ska du bestämma vilka ansvarsområden för horisontell partitionering som din dataplattform redan hanterar. Vissa tjänster hanterar horisontell partitionering helt. Azure Cosmos DB distribuerar till exempel data mellan fysiska partitioner, hanterar delningar och dirigerar frågor utan programengagemang. Andra tjänster hanterar delvis sharding. Azure SQL Database tillhandahåller till exempel elastiska databasverktyg för hantering av fragmentkartor och databeroende routning, men du utformar shardnyckeln och hanterar delade åtgärder. Använd horisontell partitioneringsmönstret när du skapar och använder horisontell partitioneringslogik själv.
Använd det här mönstret i sådana här scenarier:
Den totala datavolymen överskrider lagringskapaciteten för en enskild databasinstans och inget lodrätt skalningsalternativ åtgärdar bristen.
Transaktionsgenomströmningen eller frågekonkurrens överskrider vad en enskild instans kan hantera och läsrepliker löser inte flaskhalsen eftersom skrivbelastningen också är hög.
Anmärkning
Horisontell partitionering förbättrar prestanda och skalbarhet för ett system, och det kan också förbättra tillgängligheten. Ett fel i en partition hindrar inte nödvändigtvis ett program från att komma åt data i andra partitioner. Och en operatör kan utföra underhåll eller återställning av en partition utan att göra alla data otillgängliga. Mer information finns i Vägledning för datapartitionering.
Regel- eller efterlevnadskrav kräver att specifika dataunderuppsättningar finns i specifika geografiska jurisdiktioner, och ingen distribution i en enda region kan uppfylla alla krav.
Distinkta klientorganisationer eller kundsegment kräver fysisk dataisolering av säkerhets-, prestanda- eller avtalsskäl.
I scenarier som dessa tillämpas horisontell partitioneringsmönstret ibland utanför traditionella datalager. Till exempel kan ett DNS-zonhanteringssystem fragmenteras av team, miljö eller region för att minska explosionsradien för DNS-ändringar och upprätta tydliga ägarskapsgränser. I det sammanhanget är den primära motivationen driftssegmentering snarare än skalbarhet. Mer information finns i Horisontell partitionering av privata DNS-zoner.
Horisontell partitionering ger betydande och permanent komplexitet i din dataarkitektur. Den komplexiteten påverkar utveckling, åtgärder, testning, frågedesign och felåterställning för systemets livslängd.
Det här mönstret kanske inte är lämpligt när:
Din datavolym och dataflöde passar in i en enda databasinstans, även med beräknad tillväxt. Vertikal skalning bevarar fråge enkelhet och transaktionsintegritet.
Din flaskhals är läsvolymen, inte skrivvolymen eller lagringskapaciteten. Läsrepliker och cachelagringslager kan avlasta lästrafik utan den komplexitet mellan shardfrågor som horisontell partitionering introducerar.
Databasmotorn stöder partitionering på tabellnivå som uppfyller dina prestandabehov. Partitionering inom en enskild instans kräver inte flera servrar eller routningslogik.
Dina dominerande frågemönster kräver korsentitetskopplingar, multientitetstransaktioner eller sammansättningar av fullständiga datamängder. Horisontell partitionering gör dessa åtgärder dyra, och omkostnaderna för utskalningsfrågor och distribuerad samordning kan uppväga skalningsfördelarna.
Design av arbetsbelastning
Utvärdera hur du använder Sharding-mönstret i en arbetsbelastnings design för att hantera de mål och principer som beskrivs i Grundpelarna i Azure Well-Architected Framework. Följande tabell innehåller vägledning om hur det här mönstret stöder målen för varje pelare.
| Grundpelare | Så här stöder det här mönstret pelarmål |
|---|---|
| Tillförlitlighets designbeslut hjälper din arbetsbelastning att bli motståndskraftig mot funktionsfel och säkerställer att den återställer sig till ett fullständigt fungerande tillstånd när ett fel uppstår. | Data och bearbetning isoleras till fragmentet, så ett fel i ett fragment förblir isolerat till fragmentet. - Datapartitionering - RE:07 Självbevarande |
| Kostnadsoptimering fokuserar på att upprätthålla och förbättra arbetsbelastningens avkastning på investeringen. | Ett system som implementerar shards drar ofta nytta av att använda flera instanser av billigare beräknings- eller lagringsresurser i stället för en enda dyrare resurs. I många fall kan den här konfigurationen spara pengar. - CO:07 Komponentkostnader |
| Prestandaeffektivitet hjälper din arbetsbelastning effektivt uppfylla kraven genom optimering av skalning, data och kod. | När du använder horisontell partitionering i din skalningsstrategi isoleras data och bearbetning till varje shard, så begäranden konkurrerar bara om resurser inom deras tilldelade fragment. Du kan också använda horisontell partitionering för att optimera baserat på geografi. - PE:05 Skalning och partitionering - PE:08 Dataprestanda |
Om detta mönster inför kompromisser inom en pelare bör du överväga dem mot målen för de andra pelarna.
Exempel
Överväg en webbplats som visar en omfattande samling information om publicerade böcker över hela världen. Antalet möjliga böcker som katalogiseras i den här arbetsbelastningen och de typiska fråge- och användningsmönstren överskrider vad en enda relationsdatabas kan hantera. Arbetsbelastningsarkitekten väljer att dela upp data över flera databasinstanser med hjälp av böckernas statiska ISBN som shard-nyckel. Mer specifikt använder arkitekten kontrollsiffran (0–10) för ISBN, vilket ger 11 möjliga logiska shards med rättvist balanserad datadistribution.
Till att börja med samordnar arkitekten de 11 logiska fragmenten i tre fysiska sharddatabaser. I den här virtuella partitionsmetoden mappar många logiska partitioner till färre fysiska noder. Arkitekten använder metoden för uppslagsharding och lagrar nyckel-till-server-mappningen i en shard-kartdatabas.
Azure App Service är märkt bokkatalogswebbplats. Den ansluter till flera SQL Database-instanser och en Azure AI Search-instans. En av databaserna är märkt som ShardMap-databasen. Den innehåller en exempeltabell som speglar en del av mappningstabellen, som visas senare i den här artikeln. Tabellen innehåller tre instanser av sharddatabaser: bookdbshard0, bookdbshard1 och bookdbshard2. De andra databaserna innehåller identiska exempel på tabeller under dem. Tabellerna innehåller Böcker, LibraryOfCongressCatalog och en indikator på fler tabeller. AI Search används för fasetterad navigering och webbplatssökning. Hanterad identitet är associerad med App Service.
Karta över uppslagsshard
Shard Map-databasen innehåller följande shardmappningstabell och data.
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 |
Exempel på webbplatskod: enkel shardåtkomst
Webbplatsen är inte medveten om hur många fysiska sharddatabaser som finns (tre i det här fallet) eller logiken som mappar en shardnyckel till en databasinstans. Den vet bara att kontrollsiffran i en boks ISBN är shardnyckeln. Webbplatsen har skrivskyddad åtkomst till shardmappningsdatabasen och skriv- och läsåtkomst till alla sharddatabaser. I det här exemplet använder webbplatsen den systemhanterade identiteten för sin Azure App Service-värd för auktorisering, vilket håller hemligheter borta från anslutningssträngar.
Webbplatsen konfigureras med följande anslutningssträngar antingen i en appsettings.json fil, som du ser i det här exemplet, eller via App Service-appinställningar.
{
...
"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"
},
...
}
Följande kod visar hur webbplatsen kör en uppdateringsfråga mot arbetsbelastningens databasshardpool.
...
// 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);
}
...
I föregående exempelkod, om book.Isbn var 978-8-1130-1024-6, ska då isbnCheckDigit vara 6. Anropet OpenShardConnectionForKeyAsync(6) implementeras vanligtvis med en cache-aside-metod. Om cachelagrad shardinformation för shardnyckel 6 inte är tillgänglig, förfrågar metoden den shardmappningsdatabas som identifieras av anslutningssträngen ShardMapDb. Metoden hämtar värdet bookdbshard2 från antingen programcachen eller sharddatabasen och ersätter det med SHARD i anslutningssträngen BookDbFragment . Metoden upprättar eller återupprättar sedan en poolanslutning till bookdbshard2.database.windows.net, öppnar den och returnerar den till den anropande koden. Koden uppdaterar sedan den befintliga posten på den databasinstansen.
Exempel på webbplatskod: flera delade åtkomster
I sällsynta fall när webbplatsen kräver en direkt, tvärshardsfråga, utför applikationen en parallell fan-out-fråga över alla shards.
...
// Retrieve all shard keys.
var shardKeys = shardedDatabaseConnections.GetAllShardKeys();
// Run 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))
{
// Collect the results into a thread-safe data structure.
}
reader.Close();
}
});
...
Som ett alternativ till frågor mellan fragment kan den här arbetsbelastningen använda ett externt underhållet index i Azure AI Search för webbplatssökning eller fasetterad navigering.
Lägga till shardinstanser
Arbetsbelastningsteamet vet att om datakatalogen eller dess samtidiga användning ökar avsevärt kan de kräva mer än tre databasinstanser. Arbetsbelastningsteamet förväntar sig inte att lägga till databasservrar dynamiskt, och de accepterar avbrott i arbetsbelastningen när en ny shard är online. För att aktivera en ny shardinstans måste de flytta data från befintliga shards till den nya sharden och uppdatera shardkarttabellen. Med den här ganska statiska metoden kan arbetsbelastningen med tillförsikt cachelagra kartläggningen av shard-nyckeldatabasen i webbapplikationskoden.
Logiken för shardnyckeln i det här exemplet har en övre gräns på 11 fysiska shards. Om arbetsbelastningsteamet avgör genom belastningsuppskattning att de så småningom behöver fler än 11 databasinstanser måste de göra en invasiv ändring av shardnyckellogik. Den här ändringen omfattar noggrann planering av kodändringar och datamigrering till den nya nyckellogik.
SDK-funktioner
Utvärdera det elastiska databasklientbiblioteket i stället för att skriva anpassad kod för shard-hantering och frågerouting till SQL Database-instanser. Det här biblioteket stöder hantering av fragmentkartor, databeroende frågeroutning och frågor mellan fragment i både C# och Java.
Nästa steg
- Konsekvensnivåer i Azure Cosmos DB: Distribution av data mellan fragment medför konsekvensvägningar. Den här artikeln beskriver spektrumet av konsekvensmodeller, från stark till slutlig, och deras effekter på tillgänglighet och svarstid.
Relaterade resurser
- Horisontell, vertikal och funktionell datapartitionering: I den här artikeln beskrivs andra strategier för partitionering av data i molnet för att förbättra skalbarheten, minska konkurrensen och optimera prestanda.
- Indextabellmönster: Ibland kan du inte stödja alla frågor via designen av shard-nyckeln ensam. Ett program kan använda mönstret Indextabell för att hämta data från ett stort datalager genom att ange en annan nyckel än shardnyckeln.
- Materialiserat vymönster: För att upprätthålla prestanda för vissa frågeåtgärder kan du skapa materialiserade vyer som sammanställer och sammanfattar data, särskilt om du distribuerar dessa data mellan shards.