Vägledning för cachelagring

Cachelagring är en vanlig teknik för att förbättra prestanda och skalbarhet i system. Cachelagring skapar tillfälliga kopior av data som används ofta i ett lagringsutrymme som är placerat närmare applikationen än den ursprungliga källan. Den här metoden kan avsevärt förbättra svarstiderna för klientprogram genom att hantera data snabbare.

Cachelagring är mest effektivt när en klientinstans upprepade gånger läser samma data, särskilt om alla följande villkor gäller för det ursprungliga datalagret:

  • Datalagret är fortfarande relativt statiskt.
  • det är långsamt jämfört med cacheminnets hastighet
  • Det är föremål för en hög grad av oenighet.
  • Det är tillräckligt långt bort från klienter att nätverksfördröjningen är betydande.

Cachelagring i distribuerade program

Distribuerade program implementerar vanligtvis någon eller båda av följande strategier vid cachelagring av data:

  • Använd en privat cache, där du har data lokalt på datorn som kör ett program eller en tjänst.

  • Använd en delad cache som fungerar som en vanlig källa som flera processer och datorer kan komma åt.

I båda fallen kan du utföra cachelagring på klientsidan och på serversidan. Processen som tillhandahåller användargränssnittet för ett system, till exempel en webbläsare eller ett skrivbordsprogram, hanterar cachelagring på klientsidan. Cachelagring på serversidan utförs på distans av processen som tillhandahåller affärstjänsterna.

Privat cachelagring

Den mest grundläggande typen av cacheminne är ett minnesinternt arkiv. Den lagras i adressutrymmet för en enda process och koden som körs i den processen kommer åt cachen direkt. Den här typen av cache är snabb att komma åt. Det kan också vara ett effektivt sätt att lagra blygsamma mängder statiska data. Mängden minne som är tillgängligt på datorn begränsar vanligtvis storleken på en cache.

Om du behöver lagra mer information i cache än vad som är fysiskt möjligt i minnet, kan du skriva de cachelagrade uppgifterna till det lokala filsystemet. Det tar längre tid att komma åt data från filsystemet än om data lagras i minnet, men det bör fortfarande vara snabbare och mer tillförlitligt än att hämta data i ett nätverk.

Om du har flera instanser av ett program som använder den här modellen samtidigt har varje programinstans en egen oberoende cache som innehåller en egen kopia av data.

Tänk på en cache som en ögonblicksbild av ursprungliga data någon gång tidigare. Om dessa data inte är statiska är det troligt att olika programinstanser har olika versioner av data i sina cacheminnen. Därför kan samma fråga som utförs av dessa instanser returnera olika resultat, som visas i följande diagram.

Diagram som visar resultatet av att använda en minnesintern cache i olika instanser av ett program.

Diagram som visar cacheinkonsekvens för flera programinstanser som är anslutna till en delad SQL-databas. Till höger finns en SQL-databas som representeras som en cylinder. Längst upp till vänster finns en stor cirkel märkt programinstans A, och längst ned till vänster finns en cirkel med liknande storlek märkt programinstans B. Inuti programinstansen är A en kugghjulsikon som representerar programprocessen. Under kugghjulsikonen finns en rutnätstabell som representerar en minnesintern cache. Utanför gränsen finns en cache för etikettläsning som är en ögonblicksbild av data vid tidpunkten X. I programinstansen B finns en annan kugghjulsikon. Under kugghjulsikonen finns en rutnätstabell som representerar en minnesintern cache. Utanför gränsen finns det en cache för etikettläsning som är en ögonblicksbild av data vid tidpunkten Y. Från SQL-databasen sträcker sig en rad mot programinstansen A, den märkta programinstansen A hämtar data vid tidpunkten X och cachelagrar dem i minnet. En andra rad sträcker sig från SQL-databasen mot programinstans B, märkt programinstans B hämtar data vid tidpunkten Y och cachelagrar dem i minnet. Mellan dessa två kommentarsrader finns en anteckning med texten att informationen i databasen ändras mellan tidpunkt X och tidpunkt Y.

Delad cache

Genom att använda en delad cache kan du se till att alla programinstanser ser samma vy över cachelagrade data. Cachen finns på en separat plats, som vanligtvis finns som en del av en separat tjänst, enligt följande diagram.

Diagram som visar resultatet av program som använder en delad cache.

Diagram som visar hur en delad cachetjänst löser cacheinkonsekvensen mellan flera programinstanser som är anslutna till en SQL-databas. Längst till höger finns en SQL-databas som representeras som en cylinder. I mitten finns en ruta med etiketten delad cachetjänst som innehåller en rutnätstabell som representerar den delade cachen. Längst till vänster finns en kugghjulsikon märkt programinstans A. Under den finns en andra kugghjulsikon märkt programinstans B. En svart pil pekar från SQL-databasen till tjänstrutnätet för delad cache, vilket indikerar att databasen fyller i den delade cachen. Från den delade cachetjänsten sträcker sig två blå pilar utåt, en mot programinstansen A och en mot Programinstans B. Längst till vänster sträcker sig en böjd hakparentes lodrätt mellan de två programinstanserna, med en intilliggande etikett med texten "Båda programinstanserna ser samma cachelagrade data.". Den här etiketten och hakparentesen markerar den viktigaste fördelen med arkitekturen för delad cache: till skillnad från en minnesintern cache per instans hämtar både programinstanserna A och B data från samma centraliserade cacheminne.

En viktig fördel med metoden för delad cachelagring är skalbarhet. Många delade cachetjänster implementeras med hjälp av ett kluster med servrar och använder programvara för att distribuera data över klustret transparent. En programinstans skickar en begäran till cachetjänsten. Den underliggande infrastrukturen avgör platsen för cachelagrade data i klustret. Du kan enkelt skala cachen genom att lägga till fler servrar.

Det finns två huvudsakliga nackdelar med metoden för delad cachelagring:

  • Cachen är långsammare att komma åt eftersom den inte längre lagras lokalt med varje programinstans.
  • Implementering av en separat cachetjänst kan öka komplexiteten i lösningen.

Överväganden för att använda cachelagring

I följande avsnitt beskrivs överväganden för att utforma och använda en cache.

Bestämma när data ska cachelagrats

Cachelagring kan avsevärt förbättra prestanda, skalbarhet och tillgänglighet. Ju mer data du har och ju större antal användare som behöver komma åt dessa data, desto större är fördelarna med cachelagring. Cachelagring minskar svarstiden och konkurrensen som är associerade med hantering av stora mängder samtidiga begäranden i det ursprungliga datalagret.

En databas kan till exempel ha stöd för ett begränsat antal samtidiga anslutningar. Om du hämtar data från en delad cache i stället för den underliggande databasen kan ett klientprogram komma åt dessa data även om antalet tillgängliga anslutningar för närvarande är förbrukat. Om databasen blir otillgänglig kan klientprogram dessutom fortsätta med hjälp av data i cacheminnet.

Överväg att cachelagra data som läses ofta men ändras sällan. Till exempel cachelagrade data som har en högre andel läsåtgärder än skrivåtgärder. Använd dock inte cachen som det auktoritativa arkivet för kritisk information. Spara i stället alla viktiga ändringar i ett beständigt datalager. Om cacheminnet inte är tillgängligt kan programmet fortfarande fortsätta att fungera med hjälp av datalagret och du förlorar inte viktig information.

Bestämma hur data cachelagras effektivt

För att använda en cache effektivt behöver du avgöra vilka data som är mest lämpliga att cachelagra och cachelagra dem vid rätt tidpunkt. Du kan lägga till data i cacheminnet när ett program hämtar dem för första gången. Programmet behöver bara hämta data en gång från datalagret, och sedan kan efterföljande åtkomst uppfyllas med hjälp av cachen.

Du kan också helt eller delvis fylla i en cache med data i förväg, vanligtvis när programmet startar. Den här metoden kallas seeding. Det kanske dock inte är lämpligt att implementera seeding för en stor cache eftersom den här metoden kan medföra en plötslig, hög belastning på det ursprungliga datalagret när programmet börjar köras.

Analysera användningsmönster för att avgöra om en cache helt eller delvis ska fyllas i förväg och välja vilka data som ska cachelageras. Du kan till exempel använda cacheminnet med statiska användarprofildata för kunder som använder programmet varje dag, men inte för kunder som bara använder programmet en gång i veckan.

Cachelagring fungerar vanligtvis bra med data som inte kan ändras eller som ändras sällan. Exempel är referensinformation som produkt- och prisinformation i ett e-handelsprogram eller delade statiska resurser som är kostsamma att konstruera. Läs in vissa eller alla dessa data i cacheminnet vid programstart för att minimera efterfrågan på resurser och förbättra prestandan. Du kanske också vill ha en bakgrundsprocess som regelbundet uppdaterar referensdata i cacheminnet för att säkerställa att de är up-to-date. Eller så kan bakgrundsprocessen uppdatera cacheminnet när referensdata ändras.

Cachelagring är mindre användbart för dynamiska data, även om det finns vissa undantag. Mer information finns i avsnittet Cache för mycket dynamiska data senare i den här artikeln. När de ursprungliga data ändras regelbundet blir antingen den cachelagrade informationen inaktuell snabbt eller omkostnaderna för att synkronisera cacheminnet med det ursprungliga datalagret minskar cachelagringens effektivitet.

En cache behöver inte innehålla fullständiga data för en entitet. Om ett dataobjekt till exempel representerar ett flervärdesobjekt, till exempel en bankkund som har ett namn, en adress och ett kontosaldo, kan vissa av dessa element förbli statiska, till exempel namn och adress. Andra element, till exempel kontosaldot, kan vara mer dynamiska. I dessa situationer kan det vara användbart att cacha de statiska delarna av data och endast hämta (eller beräkna) den återstående informationen när det behövs.

Utför prestandatestning och användningsanalys för att avgöra om det är lämpligt att fylla cacheminnet i förväg, läsa in det vid behov eller använda en kombination av båda. Basera beslutet på datans volatilitet och användningsmönster. Cacheanvändning och prestandaanalys är viktiga i program som drabbas av stora belastningar och måste vara mycket skalbara. I mycket skalbara scenarier kan du till exempel använda cacheminnet för att minska belastningen på datalagret vid tider med hög belastning.

Cachelagring kan också användas för att undvika upprepade beräkningar medan programmet körs. Om en åtgärd transformerar data eller utför en komplicerad beräkning kan den spara resultatet av åtgärden i cacheminnet. Om samma beräkning krävs efteråt kan programmet hämta resultatet från cacheminnet.

Ett program kan ändra data som finns i en cache. Tänk dock på cachen som ett tillfälligt datalager som kan försvinna när som helst. Lagra inte endast värdefulla data i cacheminnet. se till att du även behåller informationen i det ursprungliga datalagret. Den här metoden minimerar risken för att förlora data om cacheminnet blir otillgängligt.

Cachelagrade mycket dynamiska data

Att lagra snabbt föränderlig information i ett beständigt datalager kan medföra en belastning på systemet. Tänk dig till exempel en enhet som kontinuerligt rapporterar status eller någon annan mätning. Om ett program väljer att inte cachelagrar dessa data på grund av att den cachelagrade informationen vanligtvis är inaktuell, kan samma överväganden gälla när du lagrar och hämtar den här informationen från datalagret. Under den tid det tar att spara och hämta dessa data kan det ändras.

I en sådan situation bör du överväga fördelarna med att lagra dynamisk information direkt i cacheminnet i stället för i det beständiga datalagret. Om data är icke-kritiska och inte kräver granskning spelar det ingen roll om enstaka ändring går förlorad.

Hantera förfallodatum för data i en cache

I de flesta fall innehåller en cache data som är en kopia av data från det ursprungliga datalagret. Data i det ursprungliga datalagret kan ändras när du har cachelagrat dem, vilket kan göra cachelagrade data inaktuella. Med många cachelagringssystem kan du konfigurera cacheminnet så att data upphör att gälla, vilket minskar den period under vilken data kan vara inaktuella.

När cachelagrade data har upphört att gälla tar cacheminnet bort dem. Programmet hämtar sedan nya data från det ursprungliga datalagret och kan ersätta utgångna data i cacheminnet. Du kan ange en standardprincip för förfallodatum när du konfigurerar cacheminnet. I många cachetjänster kan du också ange förfalloperioden för enskilda objekt när du lagrar dem programmatiskt i cacheminnet. I vissa cacheminnen kan du ange förfalloperioden som ett absolut värde eller som ett glidande värde om objektet inte nås inom en angiven tid. Den här inställningen åsidosätter alla förfalloprinciper för hela cachen, men bara för de angivna objekten.

Note

Överväg förfalloperioden för cacheminnet och de objekt som den innehåller noggrant. Om du gör det för kort går objekten ut för snabbt och du minskar fördelarna med att använda cacheminnet. Om du gör perioden för lång riskerar du att data blir inaktuella.

Om du tillåter att data finns kvar i cacheminnet under en längre tid kan cacheminnet fyllas på. I det här fallet kan alla försök att lägga till nya objekt i cacheminnet göra att cacheminnet tvingas ta bort vissa objekt i en process som kallas utrensning. Cachetjänster avlägsnar vanligtvis data på LRU-basis (minst nyligen använda), men du kan vanligtvis åsidosätta den här principen och förhindra att objekt avlägsnas. Men om du använder den här metoden riskerar du att överskrida det minne som är tillgängligt i cacheminnet. Ett program som försöker lägga till ett objekt i en fullständig cache misslyckas med ett undantag.

Vissa cachelagringsimplementeringar kan ge andra borttagningsprinciper. Exempel på typer av borttagningsprinciper är:

  • En princip som används senast: Tar bort de senast använda objekten från cacheminnet i väntan på att data inte ska krävas igen.
  • En första-in-först-ut-princip: Tar bort de äldsta data från cachen först.
  • En explicit borttagningsprincip: Tar bort objekt från cacheminnet baserat på en utlösande händelse, till exempel de data som ändras.

Ogiltigförklara data i en cache på klientsidan

Data som lagras i en cache på klientsidan anses ligga utanför kontrollen av tjänsten som tillhandahåller data till klienten. En tjänst kan inte direkt tvinga en klient att lägga till eller ta bort information från en cache på klientsidan.

Den här begränsningen innebär att en klient som använder en dåligt konfigurerad cache kan fortsätta att använda inaktuell information. Om till exempel förfalloprinciperna för cachen inte implementeras korrekt kan en klient använda inaktuell information som cachelagras lokalt när informationen i den ursprungliga datakällan ändras.

Om du skapar ett webbprogram som hanterar data via en HTTP-anslutning kan du implicit tvinga en webbklient, till exempel en webbläsare eller webbproxy, att hämta den senaste informationen. Du kan utlösa den här uppdateringen genom att ändra URI:n när du uppdaterar resursen. Webbklienter använder vanligtvis URI:n för en resurs som nyckel i cacheminnet på klientsidan, så om URI:n ändras ignorerar webbklienten alla tidigare cachelagrade versioner av en resurs och hämtar den nya versionen i stället.

Hantera samtidighet i en cache

Ofta utformar du cacheminnen som ska delas av flera instanser av ett program. Varje programinstans kan läsa och ändra data i cacheminnet, så samma samtidighetsproblem som uppstår med ett delat datalager gäller även för en cache. I en situation där ett program behöver ändra data som lagras i cacheminnet kan du behöva se till att uppdateringar som görs av en instans av programmet inte skriver över de ändringar som gjorts av en annan instans.

Beroende på typen av data och sannolikheten för kollisioner använder du något av två metoder för samtidighet:

  • Optimistisk: Innan programmet uppdaterar data kontrollerar det om data i cacheminnet har ändrats sedan de hämtades. Om data fortfarande är desamma gör programmet ändringen. I annat fall avgör programmet om det ska uppdateras. Affärslogik som styr det här beslutet är programspecifik. Den här metoden är lämplig för situationer där uppdateringar är ovanliga eller där kollisioner sannolikt inte inträffar.

  • Pessimistisk: När programmet hämtar data låser det data i cacheminnet för att förhindra att en annan instans ändrar dem. Den här processen säkerställer att kollisioner inte kan inträffa, men kan även blockera andra instanser som behöver bearbeta samma data. Pessimistisk samtidighet kan påverka skalbarheten för en lösning och rekommenderas endast för kortvariga åtgärder. Den här metoden kan vara lämplig för situationer där kollisioner är mer sannolika, särskilt om ett program uppdaterar flera objekt i cacheminnet och måste se till att dessa ändringar tillämpas konsekvent.

Implementera hög tillgänglighet och skalbarhet och förbättra prestanda

Undvik att använda en cache som den primära lagringsplatsen för data. Det ursprungliga datalagret, som cacheminnet fylls i från, hanterar den här rollen. Det ursprungliga datalagret garanterar datapersistence.

Var noga med att inte introducera kritiska beroenden om tillgängligheten för en delad cachetjänst i dina lösningar. Ett program bör kunna fortsätta att fungera om den delade cachen inte är tillgänglig. Programmet får inte svara eller misslyckas i väntan på att cachetjänsten ska återupptas.

Därför måste programmet vara förberett för att identifiera tillgängligheten för cachetjänsten och återgå till det ursprungliga datalagret om cachen är otillgänglig. MönstretCircuit-Breaker är användbart för att hantera det här scenariot. Tjänsten som tillhandahåller cacheminnet kan återställas, och när den blir tillgänglig kan cachen fyllas i igen när data läss från det ursprungliga datalagret, enligt en strategi som Cache-Aside-mönstret.

Systemets skalbarhet kan dock påverkas om programmet återgår till det ursprungliga datalagret när cachen är tillfälligt otillgänglig. Medan cacheminnet återställs kan det ursprungliga datalagret översvämmas av begäranden om data, vilket resulterar i tidsgränser och misslyckade anslutningar.

Överväg att implementera en lokal, privat cache i varje instans av ett program, tillsammans med den delade cache som alla programinstanser har åtkomst till. När programmet hämtar ett objekt kan det först checka in sin lokala cache, sedan i den delade cachen och slutligen i det ursprungliga datalagret. Den lokala cachen kan fyllas i med hjälp av data i antingen den delade cachen eller i databasen om den delade cachen inte är tillgänglig.

Den här metoden kräver noggrann konfiguration för att förhindra att den lokala cachen blir för inaktuell när det gäller den delade cachen. Den lokala cachen fungerar dock som en buffert om den delade cachen inte går att nå, enligt följande diagram.

Diagram som visar strukturen för en delad cache som kan använda en lokal privat cache som buffert.

Diagram som visar en hybridarkitektur för cachelagring. Längst till höger finns en SQL-databas som representeras som en cylinder. I det övre högra området finns en stor cirkel märkt delad cachetjänst som innehåller en rutnätstabell som representerar den delade cachen. En pil pekar åt vänster från SQL-databasen till tjänstrutnätet för delad cache, vilket indikerar att databasen fyller i den delade cachen. Längst upp till vänster finns en stor cirkel märkt programinstans A. Inuti cirkeln sitter en kugghjulsikon längst upp, och under den finns en rutnätstabell som representerar en lokal privat cache. En dubbelriktad svart pil förbinder kugghjulsikonen med rutnätet för den lokala cachen, vilket indikerar en läs- och skrivrelation mellan applikationsprocessen och dess lokala cache. Längst ned till vänster finns en stor cirkel märkt programinstans B, med samma interna struktur. Från den delade cachetjänsten sträcker sig två blå pilar utåt, en som rör sig uppåt mot kugghjulsikonen i programinstansen A och en som metar nedåt mot kugghjulsikonen i programinstans B. En rektangulär svart linje utgör en återställningssökväg som körs från SQL-databasen längs de övre och högra kanterna och sedan nedåt och längst ned och ansluter tillbaka till de lokala cacherutnäten i båda programinstanserna. En etikett längst ner i mitten av diagrammet lyder: om den delade cachetjänsten inte är tillgänglig fyller applikationslogiken den lokala cachen med data från databasen. Längst till vänster sträcker sig en böjd hakparentes mellan programinstanserna A och B, med en intilliggande etikettläsning. Om den delade cachetjänsten inte är tillgänglig kan programinstanser fortsätta att fungera med hjälp av lokala, privata cacheminnen.

För att stödja stora cacheminnen som innehåller relativt långlivade data tillhandahåller vissa cachetjänster ett alternativ med hög tillgänglighet som implementerar automatisk redundans om cachen blir otillgänglig. Den här metoden innebär vanligtvis att replikera cachelagrade data som lagras på en primär cacheserver till en sekundär cacheserver och växla till den sekundära servern om den primära servern misslyckas eller anslutningen går förlorad.

För att minska svarstiden från skrivning till flera mål kan replikeringen till den sekundära servern ske asynkront när data skrivs till cachen på den primära servern. Den här metoden leder till att viss cachelagrad information kan gå förlorad om det uppstår ett fel, men andelen av dessa data bör vara liten jämfört med cachens totala storlek.

Om en delad cache är stor kan det vara fördelaktigt att partitioneras cachelagrade data mellan noder för att minska risken för konkurrens och förbättra skalbarheten. Många delade cacheminnen stöder möjligheten att dynamiskt lägga till och ta bort noder och balansera om data mellan partitioner. Den här metoden kan omfatta klustring, där samlingen noder visas för klientprogram som en enda cache. Internt sprids dock data mellan noder efter en fördefinierad distributionsstrategi som balanserar belastningen jämnt. Mer information finns i Sharding-mönstret.

Klustring kan också öka cachens tillgänglighet. Om en nod misslyckas är resten av cacheminnet fortfarande tillgängligt. Klustring används ofta med replikering och failover. Varje nod kan replikeras, och repliken kan snabbt tas online vid nodfel.

Många läs- och skrivåtgärder kommer sannolikt att omfatta enskilda datavärden eller objekt. Ibland kan det dock vara nödvändigt att lagra eller hämta stora mängder data snabbt. Till exempel kan seeding av en cache innebära att du skriver hundratals eller tusentals objekt till cacheminnet. Ett program kan också behöva hämta ett stort antal relaterade objekt från cacheminnet som en del av samma begäran.

Många storskaliga cacheminnen tillhandahåller batchåtgärder för dessa ändamål. Med den här funktionen kan ett klientprogram paketera en stor mängd objekt i en enda begäran, vilket minskar kostnaderna för att utföra ett stort antal små begäranden.

Cachelagring och eventuell konsistens

För att det Cache-Aside mönstret ska fungera måste instansen av programmet som fyller cacheminnet ha åtkomst till den senaste och konsekventa versionen av data. I ett system som implementerar slutlig konsekvens (till exempel ett replikerat datalager) kanske det här villkoret inte är sant.

En instans av ett program kan ändra ett dataobjekt och ogiltigförklara den cachelagrade versionen av objektet. En annan instans av programmet kan försöka läsa det här objektet från en cache, vilket orsakar en cachemiss. Den läser sedan data från datalagret och lägger till dem i cacheminnet. Men om datalagret inte är helt synkroniserat med de andra replikerna kan programinstansen läsa och fylla i cacheminnet med det gamla värdet.

Ett distribuerat cacheminne introducerar ett annat lager för det här problemet. CAP-satsen anger att ett distribuerat system kan ge högst två av tre garantier: konsekvens, tillgänglighet och partitionstolerans. Eftersom nätverkspartitioner inte kan undvikas i molnmiljöer måste du välja mellan konsekvens och tillgänglighet. De flesta distribuerade cacheminnen, inklusive Redis, prioriterar tillgänglighet och partitionstolerans framför stark konsistens. Den här prioriteten innebär att läsningar från en cachereplik kan returnera inaktuella data under en nätverkspartition eller omedelbart efter en skrivning till en annan nod. När du utformar din cachestrategi, avgör hur inaktuell information applikationen kan tolerera och ange TTL-värden därefter. För data som måste vara aktuella använder du kortare TTL:er eller kringgår cachen helt och hållet och läser från källdatalagret.

Mer information om hur du hanterar datakonsekvens i distribuerade system finns i Dataöverväganden för mikrotjänster.

Skydda cachelagrade data

Oavsett vilken cachetjänst du använder bör du överväga hur du skyddar data i cacheminnet från obehörig åtkomst. Två huvudsakliga problem är:

  • Sekretessen för data i cacheminnet.
  • Datasekretessen när data flödar mellan cacheminnet och applikationen som använder det.

För att skydda data i cacheminnet kan cachetjänsten implementera en autentiseringsmekanism som kräver att program anger följande information:

  • Vilka identiteter som kan komma åt data i cacheminnet.
  • Vilka läs- och skrivåtgärder dessa identiteter tillåts utföra.

För att minska kostnaderna för läsning och skrivning av data kan identiteten använda alla data i cacheminnet när en identitet har beviljats skriv- eller läsåtkomst till cacheminnet.

Om du behöver begränsa åtkomsten till delmängder av cachelagrade data använder du någon av följande metoder:

  • Dela upp cachen i partitioner med hjälp av olika cacheservrar. Bevilja endast åtkomst till identiteter för de partitioner som de ska tillåtas att använda.

  • Kryptera data i varje delmängd med hjälp av olika nycklar. Ange endast krypteringsnycklarna till identiteter som ska ha åtkomst till varje delmängd. Ett klientprogram kanske fortfarande kan hämta alla data i cacheminnet, men det kan bara dekryptera de data som det har nycklar för.

Du måste också skydda data när de flödar in och ut ur cacheminnet. Beroende på de säkerhetsfunktioner som tillhandahålls av nätverksinfrastrukturen som klientprogram använder för att ansluta till cachen. Om cachen implementeras med hjälp av en på-plats-server i samma organisation som är värd för klientprogrammen, kanske isoleringen av själva nätverket inte kräver att du vidtar fler åtgärder. Om cacheminnet finns på distans och kräver en TCP- eller HTTP-anslutning via ett offentligt nätverk, till exempel Internet, bör du överväga att implementera TLS.

Implementera cachelagring med hjälp av Azure Managed Redis

I de återstående avsnitten i den här artikeln beskrivs hur du implementerar cachelagringsmönstren med hjälp av Azure Managed Redis. Azure Managed Redis är en hanterad Redis-tjänst som du kan använda som en delad cache mellan programinstanser. Den stöder cachelagring av nyckelvärden, datastrukturer som uppsättningar, sorterade uppsättningar och listor samt valfri beständighet för hållbarhet vid omstarter.

Information om tillgängliga nivåer, kapacitetsplanering, nätverk och funktionsinformation finns i dokumentationen om Azure Managed Redis.

Ansluta och konfigurera klientprogram

Redis stöder klientprogram på många programmeringsspråk. För .NET-program är flera klientbibliotek tillgängliga, som var och en passar för olika Redis-arbetsbelastningar. Ditt val av bibliotek beror på om du använder Redis strikt som en cache eller som en dataplattform med flera modeller.

Om du vill ansluta till en Redis-server använder du klassens Connect statiska ConnectionMultiplexer metod. Anslutningen som den här metoden skapar skapas för användning under hela klientprogrammets livslängd. Flera samtidiga trådar kan använda samma anslutning. Återanslut och koppla inte från varje gång du utför en Redis-åtgärd eftersom det kan försämra prestandan.

Exempel på språkspecifika anslutningar finns i Använd Azure Managed Redis i .NET Core.

Välj ett .NET-klientbibliotek

När du använder Azure Managed Redis för cachelagring använder du följande .NET bibliotek:

  • StackExchange.Redis: En Redis-klient på låg nivå som ger höga prestanda. Använd den när du behöver direkt åtkomst till Redis-kommandon, atomiska åtgärder, transaktioner, pipelining eller Lua-skript.

  • Microsoft. Extensions.Caching.StackExchangeRedis: Tillhandahåller en IDistributedCache-integrering för ASP.NET Core. Använd den för enkel cachelagring av nyckelvärden där värden lagras som ogenomskinliga bytematriser. Den här abstraktionen exponerar inte avancerade Redis-datastrukturer.

Dessa bibliotek tillhandahåller de primitiver som krävs för att skapa vanliga cachelagringsmönster, men programmet måste implementera själva cachelagringslogik.

Implementera cachelagringsmönster

Det enklaste sättet att använda Redis för cachelagring är att lagra värden under nycklar med hjälp av nyckel/värde-modellen. Värden kan vara strängar eller binära data med godtycklig längd, vilket gör Redis lämpligt för cachelagring av serialiserade objekt, konfigurationsdata, sessionstillstånd eller förberäknade resultat.

Utforma nyckelområdet noggrant och använd meningsfulla (men inte utförliga) nycklar. Använd till exempel strukturerade nycklar som customer:100 (i stället för bara 100) för att representera nyckeln för kunden som har ID 100. Med det här schemat kan du skilja mellan värden som lagrar olika datatyper. Du kan till exempel också använda nyckeln orders:100 för att representera nyckeln för den ordning som har ID 100.

Även om strängar är den vanligaste cachelagringsmetoden stöder Redis en omfattande uppsättning inbyggda datatyper, till exempel hashvärden, listor, uppsättningar, sorterade uppsättningar och strömmar, vilket möjliggör mer flexibla cachelagringsmönster. Mer information om Redis-datatyper finns i Redis-dokumentationen om datatyper.

Implementera mönstret Cache-Aside

Som beskrivs i Fastställ hur du cachelägger data effektivt är en vanlig metod att ladda data till cacheminnet på begäran. I följande exempel kontrolleras cachen först, hämtas från datakällan vid en miss och resultatet lagras för efterföljande begäranden:

var config = new ConfigurationOptions();
// ... configure endpoint, credentials, TLS, etc.
ConnectionMultiplexer redisHostConnection = ConnectionMultiplexer.Connect(config);
IDatabase cache = redisHostConnection.GetDatabase();

async Task<string> RetrieveItemAsync(string itemKey)
{
    // Attempt to retrieve the item from the Redis cache
    string itemValue = await cache.StringGetAsync(itemKey);

    // If the value returned is null, the item was not found in the cache
    // So retrieve the item from the data source and add it to the cache
    if (itemValue is null)
    {
        itemValue = await GetItemFromDataSourceAsync(itemKey);
        await cache.StringSetAsync(itemKey, itemValue);
    }

    return itemValue;
}

Utföra atomiska operationer och batchoperationer

När flera klienter eller programinstanser delar en cache måste du förhindra att samtidiga uppdateringar skadar data. De allmänna samtidighetsstrategierna beskrivs i Hantera samtidighet i en cache tidigare i den här artikeln. Redis innehåller flera mekanismer som implementerar dessa strategier.

  • Atomiska operationer med en enda nyckel: Använd kommandon som uppdaterar ett värde i ett enda steg, vilket eliminerar kapplöpningstillstånd som uppstår när GET och SET utfärdas separat.

    • INCR, INCRBY, DECR, DECRBY atomiskt öka eller minska ett numeriskt värde. I StackExchange.Redis använder du IDatabase.StringIncrementAsync och IDatabase.StringDecrementAsync. Dessa kommandon är användbara för räknare, hastighetsbegränsning och kvotspårning där flera klienter uppdaterar samma nyckel samtidigt.

    • GETSET atomically anger en nyckel till ett nytt värde och returnerar det tidigare värdet. I StackExchange.Redis använder du IDatabase.StringGetSetAsync:

      string oldValue = await cache.StringGetSetAsync("data:counter", 0);
      
  • Åtgärder med flera nycklar:MGET och MSET läsa eller skriva flera strängvärden i en enda tur och retur, vilket minskar nätverkskostnaderna när du behöver arbeta med flera nycklar samtidigt. Metoderna IDatabase.StringGetAsync och IDatabase.StringSetAsync är överbelastade för att stödja den här funktionen:

    // Create a list of key-value pairs
    var keysAndValues =
        new KeyValuePair<RedisKey, RedisValue>[]
        {
            new("data:key1", "value1"),
            new("data:key99", "value2"),
            new("data:key322", "value3")
        };
    
    // Store the list of key-value pairs in the cache
    await cache.StringSetAsync(keysAndValues);
    ...
    // Find all values that match a list of keys
    RedisKey[] keys = ["data:key1", "data:key99", "data:key322"];
    // Values should contain { "value1", "value2", "value3" }
    RedisValue[] values = await cache.StringGetAsync(keys);
    
  • Transaktioner (optimistisk samtidighet): Du kan använda WATCH kommandot för att övervaka en eller flera nycklar innan du startar en transaktion medMULTI/EXEC . Om någon bevakad nyckel ändras innan transaktionen startar tar Redis bort transaktionen och klienten kan försöka igen. StackExchange-biblioteket har stöd för transaktioner via ITransaction gränssnittet.

    Du skapar ett -objekt genom att använda -metoden. Du anropar kommandon till transaktionen med hjälp av de metoder som tillhandahålls av ITransaction objektet.

    Gränssnittet ITransaction ger åtkomst till en uppsättning metoder som liknar de metoder som används av IDatabase gränssnittet, förutom att alla metoder är asynkrona. Det innebär att de endast utförs när ITransaction.Execute metoden anropas. Värdet som ITransaction.Execute metoden returnerar anger om transaktionen har skapats (sant) eller om den misslyckades (falskt).

    Följande kodfragment visar ett exempel som ökar och minskar två räknare som en del av samma transaktion:

    ITransaction transaction = cache.CreateTransaction();
    
    var tx1 = transaction.StringIncrementAsync("data:counter1");
    var tx2 = transaction.StringDecrementAsync("data:counter2");
    
    bool result = await transaction.ExecuteAsync();
    
    Console.WriteLine($"Transaction {(result ? "succeeded" : "failed")}");
    
    if (result)
    {
        long increment = await tx1;
        long decrement = await tx2;
    
        Console.WriteLine($"Result of increment: {increment}");
        Console.WriteLine($"Result of decrement: {decrement}");
    }
    

    Redis-transaktioner skiljer sig från transaktioner i relationsdatabaser. Metoden Execute köar alla kommandon som utgör den transaktion som ska köras och om något kommando inte är giltigt stoppas transaktionen. Om alla kommandon har placerats i kö körs varje kommando asynkront. Om något kommando misslyckas fortsätter de andra bearbetningen. Om du behöver kontrollera att ett kommando har slutförts hämtar du resultatet med hjälp Result av egenskapen för motsvarande uppgift, som du ser i föregående exempel.

  • Lua-skript. För flerstegsuppdateringar som måste vara atomiska över flera nycklar kan du köra ett Lua-skript på servern. Redis kör hela skriptet som en enda åtgärd utan att blanda in andra kommandon.

    Note

    I klustrade implementeringar måste alla nycklar som ingår i en transaktion eller ett Lua-skript finnas i samma hash-slot. Använd hash-taggar som customer:{123}:name eller customer:{123}:email för att samplacera relaterade nycklar.

Utför brand-och-glöm-cacheåtgärder

När en cacheuppdatering inte påverkar programmets korrekthet, som att öka en visningsräknare eller uppdatera en icke-kritisk statistik, kan du hoppa över att vänta på serverns svar. I en fire-and-forget-cacheåtgärd initierar ditt program en bakgrundsaktivitet och går vidare utan att vänta på att aktiviteten ska slutföras. Redis stöder fire-and-forget-operationer, vilket minskar rundresefördröjningen för klienten, genom kommandoflaggor:

await cache.StringSetAsync("data:key1", 99);
...
cache.StringIncrement("data:key1", flags: CommandFlags.FireAndForget);

Ange nycklar som upphör att gälla automatiskt

Förfallostrategierna som beskrivs i Hantera dataförfallotid i en cache implementeras i Redis via per nyckel-TTL:er. När du lagrar ett objekt i en Redis-cache kan du ange en timeout efter vilken objektet tas bort automatiskt. Du kan också fråga hur lång tid en nyckel har innan den upphör att gälla med hjälp TTL av kommandot . Det här kommandot är tillgängligt för StackExchange-program via IDatabase.KeyTimeToLive -metoden.

Följande kodfragment visar hur du anger en förfallotid på 20 sekunder på en nyckel och frågar efter nyckelns återstående livslängd:

// Add a key with an expiration time of 20 seconds
await cache.StringSetAsync("data:key1", 99, TimeSpan.FromSeconds(20));
...
// Query how much time a key has left to live
// If the key has already expired, the KeyTimeToLive function returns null
TimeSpan? expiry = cache.KeyTimeToLive("data:key1");

Du kan också ställa in utgångstidpunkten till ett visst datum och klockslag med kommandot EXPIREAT, som är tillgängligt i StackExchange-biblioteket i form av metoden KeyExpireAsync. Den tar en DateTime-parameter:

await cache.StringSetAsync("data:key1", 99);
await cache.KeyExpireAsync("data:key1",
    new DateTime(2026, 9, 1, 0, 0, 0, DateTimeKind.Utc));

Tip

Du kan ta bort ett objekt från cachen manuellt med hjälp DEL av kommandot som är tillgängligt via StackExchange-biblioteket som IDatabase.KeyDeleteAsync metod.

När Redis når sin minnesgräns avlägsnas nycklar enligt en konfigurerad borttagningsprincip. Standardprincipen är volatile-lru, som tar bort den senast använda nyckeln som har en TTL-uppsättning. Andra principer är allkeys-lru, volatile-randomoch noeviction (vilket gör att skrivåtgärder misslyckas när minnet är fullt). Välj en borttagningsprincip baserat på om ditt program använder TTLs konsekvent och om du föredrar att skydda nycklar som inte har förfallodatum. Mer information finns i Minneshantering.

Korskorrelera cachelagrade objekt

När du cachelagr relaterade objekt behöver du ofta hitta dem efter relation i stället för enbart primärnyckel. Till exempel kan du cachelagra blogginlägg och behöver svara på frågor som "vilka inlägg delar tagg Y?" eller "vilka taggar tillhör inlägg X?"

I Azure Managed Redis är den rekommenderade metoden att använda RedisJSON och RediSearch. Lagra varje cachelagrat objekt som ett JSON-dokument med dess metadata och skapa sedan ett RediSearch-index över de fält som du behöver fråga efter. RediSearch hanterar omvända sökningar, taggbaserad filtrering, intervallfrågor och fulltextsökning utan att programmet behöver underhålla separata indexstrukturer.

För enklare scenarier kan du också använda Redis-uppsättningar för att skapa framåtriktade och omvända index manuellt. Lagra en uppsättning per post (som innehåller dess taggar) och en uppsättning per tagg (som innehåller post-ID:t):

foreach (BlogPost post in posts)
{
    string postTagsKey = $"blog:posts:{post.Id}:tags";
    await cache.SetAddAsync(
        postTagsKey, post.Tags.Select(s => (RedisValue)s).ToArray());

    foreach (var tag in post.Tags)
    {
        await cache.SetAddAsync($"tag:{tag}:blog:posts", post.Id);
    }
}

Du kan sedan fråga efter taggar för ett inlägg med hjälp SetMembersAsyncav , hitta vanliga taggar mellan inlägg med hjälp SetCombineAsync(SetOperation.Intersect, ...)av eller hitta alla inlägg för en viss tagg. Kompromissen är att ditt program måste underhålla både framåt- och omvända uppsättningar, vilket ökar komplexiteten när antalet relationer växer.

Hitta nyligen använda objekt

Många program måste spåra de senast använda eller visade objekten. En bloggwebbplats kan till exempel visa de senast lästa inläggen för en återkommande besökare. Redis-listor är ett effektivt sätt att implementera cachelagringsmönster baserade på recency. Element kan läggas till i endera änden av listan med hjälp av LPUSH eller RPUSH, och tas bort med hjälp av LPOP eller RPOP. Använd LTRIM för att begränsa listlängden och förhindra obundna minnestillväxt.

Implementera en poängtavla

Redis Sorted Sets (ZSETs) upprätthåller ordnade rangordningar genom att associera varje element med en numerisk poäng. Redis underhåller beställningen automatiskt. ZADD är O(log N), och intervallfrågor som ZRANGE och ZREVRANGE är O(log N + M), där M är antalet element som returneras, så sorterade mängder förblir effektiva även med stora antal objekt.

Lägga till objekt i en rankningslista

I följande exempel visas hur du lägger till ett blogginlägg och dess poäng i en rankningslista med hjälp ZADD av kommandot via SortedSetAddAsync:

var db = connection.GetDatabase();
string redisKey = "blog:post_rankings";

BlogPost blogPost = ...; // The blog post being ranked

await db.SortedSetAddAsync(redisKey, blogPost.Title, blogPost.Score);
Hämta rangordnade objekt

Du kan hämta objekt i stigande poängordning med hjälp SortedSetRangeByRankWithScoresAsyncav :

var entries = await db.SortedSetRangeByRankWithScoresAsync(redisKey);

foreach (var entry in entries)
{
    Console.WriteLine($"{entry.Element}: {entry.Score}");
}

Note

SortedSetRangeByRankAsync returnerar endast medlemsvärden, inte poäng.

Hämta top-N-objekt

Om du vill hämta de högst poängsatta objekten, till exempel de 10 främsta inläggen, använder du fallande ordning:

foreach (var post in await cache.SortedSetRangeByRankWithScoresAsync(
                               redisKey, 0, 9, Order.Descending))
{
    Console.WriteLine(post);
}
Hämta objekt efter poängintervall

Du kan också fråga efter objekt baserat på poänggränser i stället för rangordning:

foreach (var post in await cache.SortedSetRangeByScoreWithScoresAsync(
                               redisKey, 5000, 100000))
{
    Console.WriteLine(post);
}

Om du vill förhindra att en topplista växer på obestämd tid tar du bort gamla poster med hjälp SortedSetRemoveRangeByRankAsync av eller använder tidsomfångsnycklar (till exempel dagliga eller veckovisa rankningslistor). Du kan uppdatera poängen atomiskt med hjälp av SortedSetIncrementAsync (ZINCRBY).

Cachesessionstillstånd och HTML-utdata

Du kan använda Azure Managed Redis för att lagra sessionstillstånd och cachedata för utdata för ASP.NET Core och ASP.NET program. När du lagrar sessionsdata och renderade utdata i en delad Redis-baserad cache kan program som körs i flera instanser, till exempel i Azure App Service, Azure Kubernetes Service (AKS), Azure Container Apps eller skalningsuppsättningar för virtuella datorer, upprätthålla konsekventa användarupplevelser utan att kräva serveraffinitet.

Tip

För bästa prestanda distribuerar du programmet och Azure Managed Redis-instansen i samma Azure-region.

ASP.NET Core

ASP.NET Core-program använder abstraktion och IDistributedCache sessionsmellanprogram. Azure Managed Redis integreras med IDistributedCache via Microsoft.Extensions.Caching.StackExchangeRedis paketet.

builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = "<your-cache-name>.<region>.redis.azure.net:10000";
    options.InstanceName = "app-cache:";
});

builder.Services.AddSession();

ASP.NET Core-middleware för cachelagring av utdata kan också använda Redis som en distribuerad bakomliggande lagringsplats, vilket gör att applikationer kan dela renderade fragment eller sidor mellan alla instanser. För mer information, se ASP.NET Core output-cacheprovider för Redis.

.NET Aspire-integrering

.NET Aspire-applikationer kan använda Aspire.Hosting.Azure.Redis paketet för att deklarera en Azure Managed Redis-resurs på appvärden. Förbrukande projekt får anslutningskonfigurationen automatiskt via beroendeinmatning, vilket eliminerar manuell hantering av anslutningssträngar mellan tjänster.

// App host: declare the Azure Managed Redis resource
var cache = builder.AddAzureManagedRedis("cache");

builder.AddProject<Projects.ProductService>()
    .WithReference(cache);

Tjänster som konsumerar registrerar den distribuerade cachen på samma sätt som andra IDistributedCache tjänsteleverantörer. Mer information finns i Kom igång med Redis-integrering.

Hög tillgänglighet, skalbarhet och partitionering

Varje instans av Azure Managed Redis använder primär/replika-replikering. Tjänsten övervakar nodhälsan och främjar automatiskt en replika om primärnoden misslyckas. Eftersom replikeringen är asynkron kan en liten mängd nyligen skrivna data gå förlorade under en oväntad redundansväxling. De allmänna strategierna bakom replikering, redundans och skiktad cachelagring finns i Implementera hög tillgänglighet och skalbarhet och förbättra prestanda tidigare i den här artikeln.

Du kan kombinera en lokal minnesintern cache med Azure Managed Redis för att minska svarstiden och tillhandahålla en återställning om den delade cachen tillfälligt inte kan nås. Circuit-Breaker-mönstret och Cache-Aside-mönstret hjälper till att hantera den här skiktade metoden.

För arbetsbelastningar som överskrider kapaciteten för en enskild nod stöder Azure Managed Redis partitioneringsdata (horisontell partitionering) mellan flera Redis-noder. Med båda klustringsprinciperna partitioneras data automatiskt mellan noder med hjälp av hashning från nyckel till shard, automatisk redundans och omsynkronisering samt online-partitionering (utskalning och inskalning). Azure Managed Redis har stöd för två klustringsprinciper:

  • OSS-klustringsprincip (standard): Klienter kommunicerar direkt med rätt shard och följer OSS Redis-klustersemantik, inklusive omdirigeringar från MOVED och ASK. Klustermedvetna klienter som StackExchange.Redis hanterar dessa omdirigeringar automatiskt. Den här principen ger lägst omkostnader för routning.

  • Redis Enterprise-klustringsprincip: En proxy tillhandahåller transparent routning via en enskild slutpunkt. Klienter behöver inte implementera klustermedveten logik eller hantera MOVED/ASK-svar. Den här principen erbjuder enklare klientintegrering men medför en liten mängd routningskostnader.

Azure Managed Redis stöder också nonclustered mode, som använder ett enda primärt/replikpar utan horisontell partitionering. Det här läget är lämpligt för mindre arbetsbelastningar som inte kräver horisontell utskalning.

Note

Anpassade partitioneringsmodeller, till exempel hashning på klientsidan eller icke-Microsoft proxyservrar, behövs vanligtvis bara i självhanterade Redis-distributioner på virtuella datorer eller Kubernetes. Azure Managed Redis-klustring hanterar routning, failover och omfördelning automatiskt.

Aktiv geografisk replikering

För tillgänglighet i flera regioner stöder Azure Managed Redis aktiv geo-replikering, som länkar instanser mellan Azure regioner till en enda replikeringsgrupp. Varje instans kan hantera läsningar och skrivningar och ändringar synkroniseras automatiskt. Din applikation ansvarar för att omdirigera trafik till en funktionsduglig instans under ett regionalt fel. Mer information finns i Konfigurera aktiv geo-replikering.

Databeständighet

Som standard lagras cachelagrade data i Azure Managed Redis i minnet och kan gå förlorade om en nod startas om eller redundansväxlar. För arbetsbelastningar där det skulle vara långsamt eller dyrt att återskapa cacheminnet från källdatalagret har Azure Managed Redis stöd för valfri datapersistence:

  • RDB-ögonblicksbilder (Redis-databas) skapar periodiska ögonblicksbilder från specifika tidpunkter som sparas på en hanterad disk. RDB har minimal prestandaeffekt under normala åtgärder, men data som skrivits sedan den senaste ögonblicksbilden kan gå förlorade.

  • AOF (Append-Only File) loggar varje skrivåtgärd till disk. AOF minskar den potentiella dataförlusten till ungefär en sekund av skrivningar, men skapar större filer och kan minska skrivningsdataflödet.

Du kan använda både RDB och AOF tillsammans. Redis läser in RDB-ögonblicksbilden vid start och spelar sedan upp AOF-loggen igen för nästan fullständig återställning.

Important

Persistens ökar tåligheten vid nodfel, men är ingen mekanism för säkerhetskopiering eller katastrofåterställning. För kritiska data ska du alltid underhålla den auktoritativa kopian i källdatalagret och använda Cache-Aside-mönstret för att fylla i cacheminnet igen.

Konfigurationsinformation finns i Konfigurera datapersistence.

Skydda cachelagrade data i Azure Managed Redis

Vägledningen i Skydda cachelagrade data beskriver problem med åtkomstkontroll och data under överföring. Azure Managed Redis hjälper dig att lösa dessa problem på följande sätt:

  • Använd Microsoft Entra ID-autentisering som den primära åtkomstkontrollmekanismen och följ principen om minsta behörighet när du beviljar åtkomst.

  • Använd privata slutpunkter för att begränsa nätverksåtkomsten så att trafiken inte passerar det offentliga Internet.

  • Azure Managed Redis krypterar data under överföring med hjälp av TLS och krypterar vilande data.

Överväganden för serialisering

När du lagrar .NET-objekt i Redis som strängvärden måste du serialisera dem. När du väljer ett serialiseringsformat bör du överväga kompromisser mellan prestanda, samverkan, versionshantering och nyttolaststorlek. Det finns ingen enda snabbaste serialiserare för alla scenarier. Benchmarks är mycket beroende av kontext och kanske inte återspeglar din faktiska arbetsbelastning.

Om din Azure Managed Redis-nivå stöder RedisJSON kan du lagra objekt som interna JSON-dokument och köra frågor mot enskilda fält utan att deserialisera hela värdet:

public static class RedisJsonExtensions
{
    public static async Task<T?> GetAsync<T>(
        this IDatabase cache,
        string key,
        string path = "$")
    {
        var result = await cache.ExecuteAsync("JSON.GET", key, path);

        if (result.IsNull)
            return default;

        return JsonSerializer.Deserialize<T>(result!);
    }

    public static async Task SetAsync<T>(
        this IDatabase cache,
        string key,
        T value,
        TimeSpan? expiry = null,
        string path = "$")
    {
        var json = JsonSerializer.Serialize(value);

        // Store JSON document
        await cache.ExecuteAsync("JSON.SET", key, path, json);

        // Apply TTL if provided
        if (expiry.HasValue)
        {
            await cache.KeyExpireAsync(key, expiry);
        }
    }

    public static async Task<bool> ExpireAsync(
        this IDatabase cache,
        string key,
        TimeSpan expiry)
    {
        return await cache.KeyExpireAsync(key, expiry);
    }
}

När du i stället serialiserar värden som Redis-strängar inkluderar vanliga formatalternativ:

  • JSON – Läsbart format för människor som har brett plattformsoberoende stöd. Inte det mest kompakta formatet, men ett bra val när cachelagrade objekt returneras direkt till HTTP-klienter eftersom det undviker ett extra deserialiserings- och omialiseringssteg.

  • MessagePack – ett kompakt binärt format som inte har något schemakrav. Genererar mindre nyttolaster än JSON med lägre serialiseringskostnader.

  • Protokollbuffertar (protobuf) – ett schemabaserat binärt format som producerar kompakta nyttolaster. Kräver .proto definitionsfiler och ett kompileringssteg för att generera språkspecifik kod.

  • BSON – ett binärt format som utökar JSON med fler typer, till exempel datum och binära rådata. Nyttolaster är jämförbara i storleken med JSON. Ett praktiskt val när ditt program redan använder BSON någon annanstans, till exempel med MongoDB.

Följande mönster kan vara relevanta när du implementerar cachelagring i dina program:

  • Cache-Aside mönster: Det här mönstret beskriver hur du läser in data på begäran till en cache från ett datalager. Det hjälper också till att upprätthålla konsekvens mellan data i cacheminnet och data i det ursprungliga datalagret.

  • Mönster för horisontell partitionering: Det här mönstret innehåller information om hur du implementerar horisontell partitionering för att förbättra skalbarheten vid lagring och åtkomst till stora mängder data.